Improved contacts list search field

This commit is contained in:
Sylvain Berfini 2020-04-06 10:15:15 +02:00
parent 7e81f775c3
commit 339e30a75e
10 changed files with 86 additions and 108 deletions

View file

@ -23,7 +23,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
@ -122,6 +121,10 @@ class ChatRoomCreationFragment : Fragment() {
}
})
viewModel.filter.observe(viewLifecycleOwner, Observer {
viewModel.applyFilter()
})
adapter.selectedContact.observe(viewLifecycleOwner, Observer {
it.consume { searchResult ->
if (createGroup) {
@ -145,17 +148,6 @@ class ChatRoomCreationFragment : Fragment() {
}
}
binding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
viewModel.filter(newText ?: "")
return true
}
})
viewModel.onErrorEvent.observe(viewLifecycleOwner, Observer {
it.consume { messageResourceId ->
(activity as MainActivity).showSnackBar(messageResourceId)

View file

@ -47,9 +47,10 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
val selectedAddresses = MutableLiveData<ArrayList<Address>>()
val limeAvailable: Boolean = LinphoneUtils.isLimeAvailable()
val filter = MutableLiveData<String>()
var previousFilter = ""
private var filter: String = ""
val limeAvailable: Boolean = LinphoneUtils.isLimeAvailable()
private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() {
override fun onContactsUpdated() {
@ -95,18 +96,19 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
isEncrypted.value = encrypted
}
fun filter(search: String) {
if (filter.isNotEmpty() && filter.length > search.length) {
fun applyFilter() {
val filterValue = filter.value.orEmpty()
if (previousFilter.isNotEmpty() && previousFilter.length > filterValue.length) {
coreContext.contactsManager.magicSearch.resetSearchCache()
}
filter = search
previousFilter = filterValue
updateContactsList()
}
fun updateContactsList() {
val domain = if (sipContactsSelected.value == true) coreContext.core.defaultProxyConfig?.domain ?: "" else ""
val results = coreContext.contactsManager.magicSearch.getContactListFromFilter(filter, domain)
val results = coreContext.contactsManager.magicSearch.getContactListFromFilter(filter.value.orEmpty(), domain)
val list = arrayListOf<SearchResult>()
for (result in results) {

View file

@ -24,7 +24,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SearchView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment
@ -104,6 +103,7 @@ class MasterContactsFragment : MasterFragment() {
it.consume { contact ->
Log.i("[Contacts] Selected item in list changed: $contact")
sharedViewModel.selectedContact.value = contact
listViewModel.filter.value = ""
if (editOnClick) {
goToContactEditor()
@ -130,23 +130,16 @@ class MasterContactsFragment : MasterFragment() {
listViewModel.updateContactsList()
})
listViewModel.filter.observe(viewLifecycleOwner, Observer {
listViewModel.updateContactsList()
})
binding.setNewContactClickListener {
// Remove any previously selected contact
sharedViewModel.selectedContact.value = null
goToContactEditor()
}
binding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
listViewModel.filter(newText ?: "")
return true
}
})
val id = arguments?.getString("id")
if (id != null) {
Log.i("[Contacts] Found contact id parameter in arguments: $id")

View file

@ -35,7 +35,7 @@ class ContactsListViewModel : ViewModel() {
val contactsList = MutableLiveData<ArrayList<Contact>>()
private var filter: String = ""
val filter = MutableLiveData<String>()
private val contactsUpdatedListener = object : ContactsUpdatedListenerStub() {
override fun onContactsUpdated() {
@ -46,7 +46,6 @@ class ContactsListViewModel : ViewModel() {
init {
sipContactsSelected.value = true
filter = ""
coreContext.contactsManager.addListener(contactsUpdatedListener)
}
@ -61,10 +60,10 @@ class ContactsListViewModel : ViewModel() {
var list = arrayListOf<Contact>()
list.addAll(if (sipContactsSelected.value == true) coreContext.contactsManager.sipContacts else coreContext.contactsManager.contacts)
if (filter.isNotEmpty()) {
val filter = filter.toLowerCase(Locale.getDefault())
val filterValue = filter.value.orEmpty().toLowerCase(Locale.getDefault())
if (filterValue.isNotEmpty()) {
list = list.filter { contact ->
contact.fullName?.toLowerCase(Locale.getDefault())?.contains(filter) ?: false
contact.fullName?.toLowerCase(Locale.getDefault())?.contains(filterValue) ?: false
} as ArrayList<Contact>
}
@ -74,11 +73,6 @@ class ContactsListViewModel : ViewModel() {
}
}
fun filter(search: String) {
filter = search
updateContactsList()
}
fun deleteContacts(list: ArrayList<Contact>) {
val select = ContactsContract.Data.CONTACT_ID + " = ?"
val ops = ArrayList<ContentProviderOperation>()

View file

@ -92,6 +92,7 @@ class DialerViewModel : ViewModel() {
val addressToCall = enteredUri.value.orEmpty()
if (addressToCall.isNotEmpty()) {
coreContext.startCall(addressToCall)
eraseAll()
} else {
setLastOutgoingCallAddress()
}
@ -101,6 +102,7 @@ class DialerViewModel : ViewModel() {
val addressToCall = enteredUri.value.orEmpty()
if (addressToCall.isNotEmpty()) {
coreContext.transferCallTo(addressToCall)
eraseAll()
} else {
setLastOutgoingCallAddress()
}

View file

@ -440,3 +440,29 @@ fun setEditTextErrorListener(editText: EditText, attrChange: InverseBindingListe
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
})
}
@BindingAdapter("queryValue")
fun setSearchViewQuery(view: SearchView, query: String?) {
if (query != view.query) {
view.setQuery(query, false)
}
}
@InverseBindingAdapter(attribute = "queryValue")
fun getSearchViewQuery(view: SearchView): String? {
return view.query?.toString()
}
@BindingAdapter("queryValueAttrChanged")
fun setSearchViewQueryListener(view: SearchView, attrChange: InverseBindingListener) {
view.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
attrChange.onChange()
return true
}
})
}

View file

@ -127,27 +127,19 @@
android:layout_alignTop="@id/top_bar"
tools:layout="@layout/list_edit_top_bar_fragment" />
<RelativeLayout
<SearchView
android:id="@+id/searchBar"
queryValue="@={viewModel.filter}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:layout_below="@id/top_bar"
android:layout_toRightOf="@id/tabs_fragment"
android:layout_margin="10dp">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:paddingRight="5dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
</RelativeLayout>
android:layout_margin="10dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"

View file

@ -137,26 +137,18 @@
android:layout_alignTop="@id/top_bar"
tools:layout="@layout/list_edit_top_bar_fragment" />
<RelativeLayout
<SearchView
android:id="@+id/searchBar"
queryValue="@={viewModel.filter}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:layout_below="@id/top_bar"
android:layout_margin="10dp">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:paddingRight="5dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
</RelativeLayout>
android:layout_margin="10dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"

View file

@ -148,26 +148,19 @@
</LinearLayout>
<RelativeLayout
<SearchView
android:id="@+id/searchBar"
queryValue="@={viewModel.filter}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:layout_below="@id/top_bar"
android:layout_margin="10dp">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:paddingRight="5dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
</RelativeLayout>
android:layout_margin="10dp"
android:paddingRight="5dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
<HorizontalScrollView
android:visibility="@{viewModel.createGroupChat ? View.VISIBLE : View.GONE}"

View file

@ -126,26 +126,18 @@
android:layout_alignTop="@id/top_bar"
tools:layout="@layout/list_edit_top_bar_fragment" />
<RelativeLayout
<SearchView
android:id="@+id/searchBar"
queryValue="@={viewModel.filter}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:layout_height="40dp"
android:layout_below="@id/top_bar"
android:layout_margin="10dp">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:paddingRight="5dp"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
</RelativeLayout>
android:layout_margin="10dp"
android:gravity="center"
android:iconifiedByDefault="false"
android:inputType="textPersonName"
android:queryBackground="@color/transparent_color"
android:queryHint="@string/contact_filter_hint"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"