Merge pull request #4559 from nextcloud/search_open_conversations

Improvise search in open conversations
This commit is contained in:
Marcel Hibbe 2025-01-08 16:24:06 +01:00 committed by GitHub
commit 1f908f8bae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 22 additions and 36 deletions

View File

@ -494,7 +494,8 @@ public interface NcApi {
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /listed-room Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /listed-room
*/ */
@GET @GET
Observable<RoomsOverall> getOpenConversations(@Header("Authorization") String authorization, @Url String url); Observable<RoomsOverall> getOpenConversations(@Header("Authorization") String authorization, @Url String url,
@Query("searchTerm") String searchTerm);
@GET @GET
Observable<StatusOverall> status(@Header("Authorization") String authorization, @Url String url); Observable<StatusOverall> status(@Header("Authorization") String authorization, @Url String url);

View File

@ -25,6 +25,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.openconversations.adapters.OpenConversationsAdapter import com.nextcloud.talk.openconversations.adapters.OpenConversationsAdapter
import com.nextcloud.talk.openconversations.viewmodels.OpenConversationsViewModel import com.nextcloud.talk.openconversations.viewmodels.OpenConversationsViewModel
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.vanniktech.ui.hideKeyboardAndFocus
import com.vanniktech.ui.showKeyboardAndFocus import com.vanniktech.ui.showKeyboardAndFocus
import javax.inject.Inject import javax.inject.Inject
@ -69,9 +70,11 @@ class ListOpenConversationsActivity : BaseActivity() {
handleSearchUI(searching) handleSearchUI(searching)
} }
binding.editText.doOnTextChanged { text, _, _, count -> binding.editText.doOnTextChanged { text, _, _, count ->
adapter.filter(text.toString()) if (!text.isNullOrBlank()) {
openConversationsViewModel.updateSearchTerm(text.toString())
openConversationsViewModel.fetchConversations()
}
} }
initObservers() initObservers()
} }
@ -83,6 +86,7 @@ class ListOpenConversationsActivity : BaseActivity() {
} else { } else {
binding.searchOpenConversations.visibility = View.VISIBLE binding.searchOpenConversations.visibility = View.VISIBLE
binding.textInputLayout.visibility = View.GONE binding.textInputLayout.visibility = View.GONE
binding.editText.hideKeyboardAndFocus()
} }
} }

View File

@ -26,8 +26,6 @@ class OpenConversationsAdapter(
private val onClick: (Conversation) -> Unit private val onClick: (Conversation) -> Unit
) : ) :
ListAdapter<Conversation, OpenConversationsAdapter.OpenConversationsViewHolder>(ConversationsCallback) { ListAdapter<Conversation, OpenConversationsAdapter.OpenConversationsViewHolder>(ConversationsCallback) {
private var originalList: List<Conversation> = emptyList()
private var isFiltering = false
inner class OpenConversationsViewHolder(val itemBinding: RvItemOpenConversationBinding) : inner class OpenConversationsViewHolder(val itemBinding: RvItemOpenConversationBinding) :
RecyclerView.ViewHolder(itemBinding.root) { RecyclerView.ViewHolder(itemBinding.root) {
@ -78,33 +76,6 @@ class OpenConversationsAdapter(
val conversation = getItem(position) val conversation = getItem(position)
holder.bindItem(conversation) holder.bindItem(conversation)
} }
fun filter(text: String) {
if (text == "") {
submitList(originalList)
isFiltering = false
return
}
isFiltering = true
val newList = mutableListOf<Conversation>()
for (conversation in originalList) {
if (conversation.displayName.contains(text, true) || conversation.description!!.contains(text, true)) {
newList.add(conversation)
}
}
if (newList.isNotEmpty()) {
submitList(newList)
}
}
override fun onCurrentListChanged(previousList: MutableList<Conversation>, currentList: MutableList<Conversation>) {
if (!isFiltering) {
originalList = currentList
}
super.onCurrentListChanged(previousList, currentList)
}
} }
object ConversationsCallback : DiffUtil.ItemCallback<Conversation>() { object ConversationsCallback : DiffUtil.ItemCallback<Conversation>() {

View File

@ -11,5 +11,5 @@ import io.reactivex.Observable
interface OpenConversationsRepository { interface OpenConversationsRepository {
fun fetchConversations(): Observable<List<Conversation>> fun fetchConversations(searchTerm: String): Observable<List<Conversation>>
} }

View File

@ -21,10 +21,11 @@ class OpenConversationsRepositoryImpl(private val ncApi: NcApi, currentUserProvi
val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1)) val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1))
override fun fetchConversations(): Observable<List<Conversation>> { override fun fetchConversations(searchTerm: String): Observable<List<Conversation>> {
val roomOverall = ncApi.getOpenConversations( val roomOverall = ncApi.getOpenConversations(
credentials, credentials,
ApiUtils.getUrlForOpenConversations(apiVersion, currentUser.baseUrl!!) ApiUtils.getUrlForOpenConversations(apiVersion, currentUser.baseUrl!!),
searchTerm
) )
return roomOverall.map { it.ocs?.data!! } return roomOverall.map { it.ocs?.data!! }
} }

View File

@ -32,14 +32,22 @@ class OpenConversationsViewModel @Inject constructor(private val repository: Ope
val viewState: LiveData<ViewState> val viewState: LiveData<ViewState>
get() = _viewState get() = _viewState
private val _searchTerm: MutableLiveData<String> = MutableLiveData("")
val searchTerm: LiveData<String>
get() = _searchTerm
fun fetchConversations() { fun fetchConversations() {
_viewState.value = FetchConversationsStartState _viewState.value = FetchConversationsStartState
repository.fetchConversations() repository.fetchConversations(_searchTerm.value ?: "")
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(FetchConversationsObserver()) ?.subscribe(FetchConversationsObserver())
} }
fun updateSearchTerm(newTerm: String) {
_searchTerm.value = newTerm
}
inner class FetchConversationsObserver : Observer<List<Conversation>> { inner class FetchConversationsObserver : Observer<List<Conversation>> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
// unused atm // unused atm

View File

@ -57,6 +57,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/nc_search" android:hint="@string/nc_search"
android:textColorHint="@color/low_emphasis_text" android:textColorHint="@color/low_emphasis_text"
android:singleLine="true"
android:textColor = "@color/high_emphasis_text"/> android:textColor = "@color/high_emphasis_text"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.MaterialToolbar>