mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 19:38:08 +00:00
Added setting to choose whether to sort contacts by first or last name
This commit is contained in:
parent
0b6805a73c
commit
dee684b364
11 changed files with 144 additions and 13 deletions
|
|
@ -167,6 +167,13 @@ class CorePreferences
|
|||
|
||||
// Contacts related
|
||||
|
||||
@get:WorkerThread @set:WorkerThread
|
||||
var sortContactsByFirstName: Boolean
|
||||
get() = config.getBool("ui", "sort_contacts_by_first_name", true) // If disabled, last name will be used
|
||||
set(value) {
|
||||
config.setBool("ui", "sort_contacts_by_first_name", value)
|
||||
}
|
||||
|
||||
@get:WorkerThread @set:WorkerThread
|
||||
var contactsFilter: String
|
||||
get() = config.getString("ui", "contacts_filter", "")!! // Default value must be empty!
|
||||
|
|
|
|||
|
|
@ -125,12 +125,12 @@ class ContactsListAdapter(
|
|||
|
||||
val previousItem = bindingAdapterPosition - 1
|
||||
val previousLetter = if (previousItem >= 0) {
|
||||
getItem(previousItem).contactName?.get(0).toString()
|
||||
getItem(previousItem).sortingName?.get(0).toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
val currentLetter = contactModel.contactName?.get(0).toString()
|
||||
val currentLetter = contactModel.sortingName?.get(0).toString()
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
firstContactStartingByThatLetter = displayLetter
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.content.FileProvider
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.observe
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
|
@ -181,9 +182,7 @@ class ContactsListFragment : AbstractMainFragment() {
|
|||
showFilterPopupMenu(binding.topBar.extraAction)
|
||||
}
|
||||
|
||||
sharedViewModel.showContactEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
sharedViewModel.showContactEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { refKey ->
|
||||
Log.i("$TAG Displaying contact with ref key [$refKey]")
|
||||
val navController = binding.contactsNavContainer.findNavController()
|
||||
|
|
@ -194,9 +193,7 @@ class ContactsListFragment : AbstractMainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
sharedViewModel.showNewContactEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
sharedViewModel.showNewContactEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
if (findNavController().currentDestination?.id == R.id.contactsListFragment) {
|
||||
Log.i("$TAG Opening contact editor for creating new contact")
|
||||
|
|
@ -207,6 +204,12 @@ class ContactsListFragment : AbstractMainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
sharedViewModel.forceRefreshContactsList.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
listViewModel.filter()
|
||||
}
|
||||
}
|
||||
|
||||
// AbstractMainFragment related
|
||||
|
||||
listViewModel.title.value = getString(R.string.bottom_navigation_contacts_label)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.linphone.core.tools.Log
|
|||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.TimestampUtils
|
||||
import androidx.core.net.toUri
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
|
||||
class ContactAvatarModel
|
||||
@WorkerThread
|
||||
|
|
@ -56,7 +57,9 @@ class ContactAvatarModel
|
|||
|
||||
val name = MutableLiveData<String>()
|
||||
|
||||
val firstLetter: String = AppUtils.getFirstLetter(friend.name.orEmpty())
|
||||
var sortingName: String? = null
|
||||
|
||||
var firstLetter: String? = null
|
||||
|
||||
private val friendListener = object : FriendListenerStub() {
|
||||
@WorkerThread
|
||||
|
|
@ -76,6 +79,7 @@ class ContactAvatarModel
|
|||
}
|
||||
|
||||
update(address)
|
||||
refreshSortingName()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
@ -85,6 +89,12 @@ class ContactAvatarModel
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun refreshSortingName() {
|
||||
sortingName = getNameToUseForSorting()
|
||||
firstLetter = AppUtils.getFirstLetter(getNameToUseForSorting().orEmpty())
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun update(address: Address?) {
|
||||
updateSecurityLevel(address)
|
||||
|
|
@ -148,6 +158,13 @@ class ContactAvatarModel
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getNameToUseForSorting(): String? {
|
||||
val sortByFirstName = corePreferences.sortContactsByFirstName
|
||||
val firstOrLastName = if (sortByFirstName) friend.vcard?.givenName else friend.vcard?.familyName
|
||||
return firstOrLastName ?: friend.name ?: friend.organization ?: friend.vcard?.fullName
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getAvatarUri(friend: Friend): Uri? {
|
||||
val picturePath = friend.photo
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ class ContactsListViewModel
|
|||
val list = arrayListOf<ContactAvatarModel>()
|
||||
val favouritesList = arrayListOf<ContactAvatarModel>()
|
||||
var count = 0
|
||||
val collator = Collator.getInstance(Locale.getDefault())
|
||||
|
||||
for (result in results) {
|
||||
val friend = result.friend
|
||||
|
|
@ -308,6 +309,7 @@ class ContactsListViewModel
|
|||
} else {
|
||||
coreContext.contactsManager.getContactAvatarModelForAddress(result.address)
|
||||
}
|
||||
model.refreshSortingName()
|
||||
|
||||
list.add(model)
|
||||
count += 1
|
||||
|
|
@ -319,16 +321,18 @@ class ContactsListViewModel
|
|||
}
|
||||
|
||||
if (firstLoad && count == 20) {
|
||||
list.sortWith { model1, model2 ->
|
||||
collator.compare(model1.getNameToUseForSorting(), model2.getNameToUseForSorting())
|
||||
}
|
||||
contactsList.postValue(list)
|
||||
}
|
||||
}
|
||||
|
||||
val collator = Collator.getInstance(Locale.getDefault())
|
||||
favouritesList.sortWith { model1, model2 ->
|
||||
collator.compare(model1.friend.name, model2.friend.name)
|
||||
collator.compare(model1.getNameToUseForSorting(), model2.getNameToUseForSorting())
|
||||
}
|
||||
list.sortWith { model1, model2 ->
|
||||
collator.compare(model1.friend.name, model2.friend.name)
|
||||
collator.compare(model1.getNameToUseForSorting(), model2.getNameToUseForSorting())
|
||||
}
|
||||
|
||||
favourites.postValue(favouritesList)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.linphone.ui.main.fragment.GenericMainFragment
|
|||
import org.linphone.utils.ConfirmationDialogModel
|
||||
import org.linphone.ui.main.settings.viewmodel.SettingsViewModel
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class SettingsFragment : GenericMainFragment() {
|
||||
|
|
@ -49,6 +50,20 @@ class SettingsFragment : GenericMainFragment() {
|
|||
|
||||
private lateinit var viewModel: SettingsViewModel
|
||||
|
||||
private val sortContactsByListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
val label = viewModel.sortContactsByNames[position]
|
||||
val value = viewModel.sortContactsByValues[position]
|
||||
Log.i("$TAG Selected contact sorting is now [$label] ($value)")
|
||||
viewModel.setContactSorting(value)
|
||||
|
||||
sharedViewModel.forceRefreshContactsList.postValue(Event(true))
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
}
|
||||
}
|
||||
|
||||
private val layoutListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
val label = viewModel.availableLayoutsNames[position]
|
||||
|
|
@ -155,6 +170,22 @@ class SettingsFragment : GenericMainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
// Setup sort contacts by spinner
|
||||
val sortContactsByAdapter = ArrayAdapter(
|
||||
requireContext(),
|
||||
R.layout.drop_down_item,
|
||||
viewModel.sortContactsByNames
|
||||
)
|
||||
sortContactsByAdapter.setDropDownViewResource(R.layout.generic_dropdown_cell)
|
||||
binding.contactsSettings.sortContactsByFirstNameSpinner.adapter = sortContactsByAdapter
|
||||
|
||||
viewModel.sortContactsBy.observe(viewLifecycleOwner) { sort ->
|
||||
binding.contactsSettings.sortContactsByFirstNameSpinner.setSelection(
|
||||
viewModel.sortContactsByValues.indexOf(sort)
|
||||
)
|
||||
}
|
||||
binding.contactsSettings.sortContactsByFirstNameSpinner.onItemSelectedListener = sortContactsByListener
|
||||
|
||||
viewModel.addLdapServerEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
if (findNavController().currentDestination?.id == R.id.settingsFragment) {
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ class SettingsViewModel
|
|||
// Contacts settings
|
||||
val showContactsSettings = MutableLiveData<Boolean>()
|
||||
|
||||
val sortContactsBy = MutableLiveData<Int>()
|
||||
val sortContactsByNames = arrayListOf(
|
||||
AppUtils.getString(R.string.contact_editor_first_name),
|
||||
AppUtils.getString(R.string.contact_editor_last_name),
|
||||
)
|
||||
val sortContactsByValues = arrayListOf(0, 1)
|
||||
|
||||
val ldapAvailable = MutableLiveData<Boolean>()
|
||||
val ldapServers = MutableLiveData<List<CardDavLdapModel>>()
|
||||
|
||||
|
|
@ -293,6 +300,8 @@ class SettingsViewModel
|
|||
corePreferences.markConversationAsReadWhenDismissingMessageNotification
|
||||
)
|
||||
|
||||
sortContactsBy.postValue(if (corePreferences.sortContactsByFirstName) 0 else 1)
|
||||
|
||||
defaultLayout.postValue(core.defaultConferenceLayout.toInt())
|
||||
|
||||
theme.postValue(corePreferences.darkMode)
|
||||
|
|
@ -467,6 +476,13 @@ class SettingsViewModel
|
|||
expandContacts.value = expandContacts.value == false
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun setContactSorting(sortingValue: Int) {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
corePreferences.sortContactsByFirstName = sortingValue == 0
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun addLdapServer() {
|
||||
addLdapServerEvent.value = Event(true)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,10 @@ class SharedMainViewModel
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val forceRefreshContactsList: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
var sipAddressToAddToNewContact: String = ""
|
||||
|
||||
// Call logs related
|
||||
|
|
|
|||
|
|
@ -15,6 +15,53 @@
|
|||
android:paddingBottom="20dp"
|
||||
android:background="@drawable/shape_squircle_white_background">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/settings_title_style"
|
||||
android:id="@+id/sort_contacts_by_first_name_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/settings_contacts_sort_by_first_name_title"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
style="@style/material_switch_style"
|
||||
android:id="@+id/sort_contacts_by_first_name_spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:paddingStart="@dimen/spinner_start_padding"
|
||||
android:paddingEnd="@dimen/spinner_end_padding"
|
||||
android:overlapAnchor="false"
|
||||
android:spinnerMode="dropdown"
|
||||
android:popupBackground="@drawable/shape_squircle_white_background"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintTop_toBottomOf="@id/sort_contacts_by_first_name_title"
|
||||
app:layout_constraintStart_toStartOf="@id/sort_contacts_by_first_name_title"
|
||||
app:layout_constraintEnd_toEndOf="@id/sort_contacts_by_first_name_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sort_contacts_by_first_name_spinner_caret"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spinner_caret_end_margin"
|
||||
android:src="@drawable/caret_down"
|
||||
android:contentDescription="@string/content_description_spinner_caret"
|
||||
app:tint="?attr/color_main2_600"
|
||||
app:layout_constraintTop_toTopOf="@id/sort_contacts_by_first_name_spinner"
|
||||
app:layout_constraintBottom_toBottomOf="@id/sort_contacts_by_first_name_spinner"
|
||||
app:layout_constraintEnd_toEndOf="@id/sort_contacts_by_first_name_spinner"/>
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/settings_title_style"
|
||||
android:onClick="@{() -> viewModel.addLdapServer()}"
|
||||
|
|
@ -31,7 +78,7 @@
|
|||
android:drawableEnd="@drawable/caret_right"
|
||||
android:drawableTint="?attr/color_main2_600"
|
||||
android:visibility="@{viewModel.ldapAvailable ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/sort_contacts_by_first_name_spinner"
|
||||
app:layout_constraintBottom_toTopOf="@id/existing_ldap_servers"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@
|
|||
<string name="settings_conversations_auto_export_media_to_native_gallery_title">Rendre visible dans la galerie les médias téléchargés</string>
|
||||
<string name="settings_conversations_mark_as_read_when_dismissing_notif_title">Marquer la conversation comme lue lorsqu\'une notification de message est supprimée</string>
|
||||
<string name="settings_contacts_title">Contacts</string>
|
||||
<string name="settings_contacts_sort_by_first_name_title">Trier les contacts par</string>
|
||||
<string name="settings_contacts_add_ldap_server_title">Ajouter un serveur LDAP</string>
|
||||
<string name="settings_contacts_edit_ldap_server_title">Editer le serveur LDAP</string>
|
||||
<string name="settings_contacts_add_carddav_server_title">Ajouter un carnet d\'adresse CardDAV</string>
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@
|
|||
<string name="settings_conversations_auto_export_media_to_native_gallery_title">Make downloaded media public</string>
|
||||
<string name="settings_conversations_mark_as_read_when_dismissing_notif_title">Mark conversation as read when dismissing message notification</string>
|
||||
<string name="settings_contacts_title">Contacts</string>
|
||||
<string name="settings_contacts_sort_by_first_name_title">Sort contacts by</string>
|
||||
<string name="settings_contacts_add_ldap_server_title">Add LDAP server</string>
|
||||
<string name="settings_contacts_edit_ldap_server_title">Edit LDAP server</string>
|
||||
<string name="settings_contacts_add_carddav_server_title">Add CardDAV address book</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue