mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 03:16:02 +03:00
Use sender data return from search result
This commit is contained in:
parent
4649b2ac1d
commit
3705fa14bd
11 changed files with 69 additions and 37 deletions
|
@ -83,6 +83,7 @@ interface Room :
|
|||
* @param beforeLimit how many events before the result are returned.
|
||||
* @param afterLimit how many events after the result are returned.
|
||||
* @param includeProfile requests that the server returns the historic profile information for the users that sent the events that were returned.
|
||||
* @param callback Callback to get the search result
|
||||
*/
|
||||
fun search(searchTerm: String,
|
||||
nextBatch: String?,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.matrix.android.sdk.api.session.search
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
/**
|
||||
* Domain class to represent the response of a search request in a room.
|
||||
|
@ -35,5 +36,10 @@ data class SearchResult(
|
|||
/**
|
||||
* List of results in the requested order.
|
||||
*/
|
||||
val results: List<Event>? = null
|
||||
val results: List<EventAndSender>? = null
|
||||
)
|
||||
|
||||
data class EventAndSender(
|
||||
val event: Event,
|
||||
val sender: MatrixItem.UserItem?
|
||||
)
|
||||
|
|
|
@ -36,6 +36,7 @@ interface SearchService {
|
|||
* @param beforeLimit how many events before the result are returned.
|
||||
* @param afterLimit how many events after the result are returned.
|
||||
* @param includeProfile requests that the server returns the historic profile information for the users that sent the events that were returned.
|
||||
* @param callback Callback to get the search result
|
||||
*/
|
||||
fun search(searchTerm: String,
|
||||
roomId: String,
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
package org.matrix.android.sdk.internal.session.search
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.matrix.android.sdk.api.session.search.EventAndSender
|
||||
import org.matrix.android.sdk.api.session.search.SearchResult
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.search.request.SearchRequestBody
|
||||
import org.matrix.android.sdk.internal.session.search.request.SearchRequestCategories
|
||||
|
@ -76,7 +78,21 @@ internal class DefaultSearchTask @Inject constructor(
|
|||
return SearchResult(
|
||||
nextBatch = searchCategories.roomEvents?.nextBatch,
|
||||
highlights = searchCategories.roomEvents?.highlights,
|
||||
results = searchCategories.roomEvents?.results?.map { it.event }?.reversed()
|
||||
results = searchCategories.roomEvents?.results?.map { searchResponseItem ->
|
||||
EventAndSender(
|
||||
searchResponseItem.event,
|
||||
searchResponseItem.event.senderId?.let { senderId ->
|
||||
searchResponseItem.context?.profileInfo?.get(senderId)
|
||||
?.let {
|
||||
MatrixItem.UserItem(
|
||||
senderId,
|
||||
it["displayname"] as? String,
|
||||
it["avatar_url"] as? String
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}?.reversed()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,5 +38,5 @@ internal data class SearchResponseEventContext(
|
|||
val end: String? = null,
|
||||
// The historic profile information of the users that sent the events returned. The string key is the user ID for which the profile belongs to.
|
||||
@Json(name = "profile_info")
|
||||
val profileInfo: JsonDict? = null
|
||||
val profileInfo: Map<String, JsonDict>? = null
|
||||
)
|
||||
|
|
|
@ -70,7 +70,8 @@ class SearchActivity : VectorBaseActivity() {
|
|||
|
||||
fun newIntent(context: Context, args: SearchArgs): Intent {
|
||||
return Intent(context, SearchActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
// If we do that we will have the same room two times on the stack. Let's allow infinite stack for the moment.
|
||||
// flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
putExtra(MvRx.KEY_ARG, args)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ class SearchFragment @Inject constructor(
|
|||
is Loading -> {
|
||||
stateView.state = StateView.State.Loading
|
||||
}
|
||||
is Fail -> {
|
||||
is Fail -> {
|
||||
stateView.state = StateView.State.Error(errorFormatter.toHumanReadable(state.asyncSearchRequest.error))
|
||||
}
|
||||
is Success -> {
|
||||
|
@ -100,8 +100,7 @@ class SearchFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
val lastBatchSize = state.lastBatch?.size ?: 0
|
||||
pendingScrollToPosition = if (lastBatchSize > 0) lastBatchSize - 1 else 0
|
||||
pendingScrollToPosition = (state.lastBatchSize - 1).coerceAtLeast(0)
|
||||
|
||||
stateView.state = StateView.State.Content
|
||||
controller.setData(state)
|
||||
|
|
|
@ -25,6 +25,8 @@ import im.vector.app.core.ui.list.genericItemHeader
|
|||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.search.EventAndSender
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import java.util.Calendar
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -62,15 +64,15 @@ class SearchResultController @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
buildSearchResultItems(data.searchResult.orEmpty())
|
||||
buildSearchResultItems(data.searchResult)
|
||||
}
|
||||
|
||||
private fun buildSearchResultItems(events: List<Event>) {
|
||||
private fun buildSearchResultItems(events: List<EventAndSender>) {
|
||||
var lastDate: Calendar? = null
|
||||
|
||||
events.forEach { event ->
|
||||
events.forEach { eventAndSender ->
|
||||
val eventDate = Calendar.getInstance().apply {
|
||||
timeInMillis = event.originServerTs ?: System.currentTimeMillis()
|
||||
timeInMillis = eventAndSender.event.originServerTs ?: System.currentTimeMillis()
|
||||
}
|
||||
if (lastDate?.get(Calendar.DAY_OF_YEAR) != eventDate.get(Calendar.DAY_OF_YEAR)) {
|
||||
genericItemHeader {
|
||||
|
@ -81,13 +83,13 @@ class SearchResultController @Inject constructor(
|
|||
lastDate = eventDate
|
||||
|
||||
searchResultItem {
|
||||
id(event.eventId)
|
||||
id(eventAndSender.event.eventId)
|
||||
avatarRenderer(avatarRenderer)
|
||||
dateFormatter(dateFormatter)
|
||||
event(event)
|
||||
// I think we should use the data returned by the server?
|
||||
sender(event.senderId?.let { session.getUser(it) })
|
||||
listener { listener?.onItemClicked(event) }
|
||||
event(eventAndSender.event)
|
||||
sender(eventAndSender.sender
|
||||
?: eventAndSender.event.senderId?.let { session.getUser(it) }?.toMatrixItem())
|
||||
listener { listener?.onItemClicked(eventAndSender.event) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ import im.vector.app.core.epoxy.ClickListener
|
|||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_search_result)
|
||||
abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
|
||||
|
@ -38,15 +38,15 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
|
|||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||
@EpoxyAttribute var dateFormatter: VectorDateFormatter? = null
|
||||
@EpoxyAttribute lateinit var event: Event
|
||||
@EpoxyAttribute var sender: User? = null
|
||||
@EpoxyAttribute var sender: MatrixItem? = null
|
||||
@EpoxyAttribute var listener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
|
||||
holder.view.onClick(listener)
|
||||
sender?.toMatrixItem()?.let { avatarRenderer.render(it, holder.avatarImageView) }
|
||||
holder.memberNameView.text = sender?.getBestName()
|
||||
sender?.let { avatarRenderer.render(it, holder.avatarImageView) }
|
||||
holder.memberNameView.setTextOrHide(sender?.getBestName())
|
||||
holder.timeView.text = dateFormatter?.format(event.originServerTs, DateFormatKind.MESSAGE_SIMPLE)
|
||||
// TODO Improve that (use formattedBody, etc.)
|
||||
holder.contentView.text = event.content?.get("body") as? String
|
||||
|
|
|
@ -69,9 +69,14 @@ class SearchViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun handleSearchWith(action: SearchAction.SearchWith) {
|
||||
if (action.searchTerm.length > 1) {
|
||||
if (action.searchTerm.isNotEmpty()) {
|
||||
setState {
|
||||
copy(searchTerm = action.searchTerm)
|
||||
copy(
|
||||
searchResult = emptyList(),
|
||||
hasMoreResult = false,
|
||||
lastBatchSize = 0,
|
||||
searchTerm = action.searchTerm
|
||||
)
|
||||
}
|
||||
startSearching(false)
|
||||
}
|
||||
|
@ -100,9 +105,7 @@ class SearchViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
if (state.asyncSearchRequest is Loading) {
|
||||
currentTask?.cancel()
|
||||
}
|
||||
currentTask?.cancel()
|
||||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
|
@ -118,24 +121,22 @@ class SearchViewModel @AssistedInject constructor(
|
|||
callback = it
|
||||
)
|
||||
}
|
||||
onSearchResultSuccess(result, isNextBatch)
|
||||
onSearchResultSuccess(result)
|
||||
} catch (failure: Throwable) {
|
||||
if (failure is Failure.Cancelled) return@launch
|
||||
|
||||
_viewEvents.post(SearchViewEvents.Failure(failure))
|
||||
setState {
|
||||
copy(
|
||||
asyncSearchRequest = Fail(failure),
|
||||
searchResult = null
|
||||
asyncSearchRequest = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSearchResultSuccess(searchResult: SearchResult, isNextBatch: Boolean) = withState { state ->
|
||||
// Accumulate results if it is the next batch
|
||||
val accumulatedResult = searchResult.results.orEmpty().plus(state.searchResult?.takeIf { isNextBatch }.orEmpty())
|
||||
private fun onSearchResultSuccess(searchResult: SearchResult) = withState { state ->
|
||||
val accumulatedResult = searchResult.results.orEmpty().plus(state.searchResult)
|
||||
|
||||
// Note: We do not care about the highlights for the moment, but it will be the same algorithm
|
||||
|
||||
|
@ -145,9 +146,14 @@ class SearchViewModel @AssistedInject constructor(
|
|||
copy(
|
||||
searchResult = accumulatedResult,
|
||||
hasMoreResult = !nextBatch.isNullOrEmpty(),
|
||||
lastBatch = searchResult.results,
|
||||
lastBatchSize = searchResult.results.orEmpty().size,
|
||||
asyncSearchRequest = Success(Unit)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
currentTask?.cancel()
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@ package im.vector.app.features.home.room.detail.search
|
|||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.search.EventAndSender
|
||||
|
||||
data class SearchViewState(
|
||||
// Accumulated search result
|
||||
val searchResult: List<Event>? = null,
|
||||
val searchResult: List<EventAndSender> = emptyList(),
|
||||
val hasMoreResult: Boolean = false,
|
||||
// Last batch result will help RecyclerView to position itself
|
||||
val lastBatch: List<Event>? = null,
|
||||
// Last batch size, will help RecyclerView to position itself
|
||||
val lastBatchSize: Int = 0,
|
||||
val searchTerm: String? = null,
|
||||
val roomId: String = "",
|
||||
// Current pagination request
|
||||
|
|
Loading…
Reference in a new issue