mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Fixed issue with first letter displayed when refreshing contacts list
This commit is contained in:
parent
20fbeda124
commit
92835a1e10
7 changed files with 142 additions and 139 deletions
|
|
@ -90,7 +90,7 @@ class ContactsManager @UiThread constructor() {
|
|||
|
||||
@WorkerThread
|
||||
override fun onFriendListRemoved(core: Core, friendList: FriendList) {
|
||||
Log.i("$TAG Friend list [${friendList.displayName}] remoed")
|
||||
Log.i("$TAG Friend list [${friendList.displayName}] removed")
|
||||
friendList.removeListener(friendListListener)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,17 @@ class ContactsListAdapter(
|
|||
|
||||
binding.root.isSelected = bindingAdapterPosition == selectedAdapterPosition
|
||||
|
||||
val previousItem = bindingAdapterPosition - 1
|
||||
val previousLetter = if (previousItem >= 0) {
|
||||
getItem(previousItem).contactName?.get(0).toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
val currentLetter = contactModel.contactName?.get(0).toString()
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
firstContactStartingByThatLetter = displayLetter
|
||||
|
||||
executePendingBindings()
|
||||
}
|
||||
}
|
||||
|
|
@ -127,12 +138,11 @@ class ContactsListAdapter(
|
|||
|
||||
private class ContactDiffCallback : DiffUtil.ItemCallback<ContactAvatarModel>() {
|
||||
override fun areItemsTheSame(oldItem: ContactAvatarModel, newItem: ContactAvatarModel): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
return oldItem.id == newItem.id && oldItem.contactName == newItem.contactName
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: ContactAvatarModel, newItem: ContactAvatarModel): Boolean {
|
||||
return oldItem.firstContactStartingByThatLetter.value == newItem.firstContactStartingByThatLetter.value &&
|
||||
oldItem.presenceStatus.value == newItem.presenceStatus.value &&
|
||||
return oldItem.presenceStatus.value == newItem.presenceStatus.value &&
|
||||
(newItem.presenceStatus.value == ConsolidatedPresence.Busy || newItem.presenceStatus.value == ConsolidatedPresence.Online)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac
|
|||
|
||||
val id = friend.refKey ?: friend.name
|
||||
|
||||
val contactName = friend.name
|
||||
|
||||
val starred = friend.starred
|
||||
|
||||
val lastPresenceInfo = MutableLiveData<String>()
|
||||
|
|
@ -52,8 +54,6 @@ class ContactAvatarModel @WorkerThread constructor(val friend: Friend) : Abstrac
|
|||
|
||||
val firstLetter: String = AppUtils.getFirstLetter(friend.name.orEmpty())
|
||||
|
||||
val firstContactStartingByThatLetter = MutableLiveData<Boolean>()
|
||||
|
||||
private val friendListener = object : FriendListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onPresenceReceived(fr: Friend) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.annotation.WorkerThread
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import java.io.File
|
||||
import java.text.Collator
|
||||
import java.util.ArrayList
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -110,6 +111,18 @@ class ContactsListViewModel @UiThread constructor() : AbstractTopBarViewModel()
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun filter() {
|
||||
isListFiltered.value = currentFilter.isNotEmpty()
|
||||
coreContext.postOnCoreThread {
|
||||
applyFilter(
|
||||
currentFilter,
|
||||
if (limitSearchToLinphoneAccounts) corePreferences.defaultDomain else "",
|
||||
MagicSearch.Source.Friends.toInt() or MagicSearch.Source.LdapServers.toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyCurrentDefaultAccountFilter() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
|
|
@ -135,63 +148,6 @@ class ContactsListViewModel @UiThread constructor() : AbstractTopBarViewModel()
|
|||
showFavourites.value = showFavourites.value == false
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("$TAG Processing [${results.size}] results")
|
||||
|
||||
val list = arrayListOf<ContactAvatarModel>()
|
||||
val favouritesList = arrayListOf<ContactAvatarModel>()
|
||||
var previousLetter = ""
|
||||
var count = 0
|
||||
|
||||
for (result in results) {
|
||||
val friend = result.friend
|
||||
|
||||
val model = if (friend != null) {
|
||||
coreContext.contactsManager.getContactAvatarModelForFriend(friend)
|
||||
} else {
|
||||
coreContext.contactsManager.getContactAvatarModelForAddress(result.address)
|
||||
}
|
||||
|
||||
val currentLetter = model.friend.name?.get(0).toString()
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
if (currentLetter != previousLetter) {
|
||||
previousLetter = currentLetter
|
||||
}
|
||||
model.firstContactStartingByThatLetter.postValue(displayLetter)
|
||||
|
||||
list.add(model)
|
||||
count += 1
|
||||
|
||||
if (friend?.starred == true) {
|
||||
favouritesList.add(model)
|
||||
}
|
||||
|
||||
if (count == 20) {
|
||||
contactsList.postValue(list)
|
||||
fetchInProgress.postValue(false)
|
||||
}
|
||||
}
|
||||
|
||||
favourites.postValue(favouritesList)
|
||||
contactsList.postValue(list)
|
||||
fetchInProgress.postValue(false)
|
||||
|
||||
Log.i("$TAG Processed [${results.size}] results")
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun filter() {
|
||||
isListFiltered.value = currentFilter.isNotEmpty()
|
||||
coreContext.postOnCoreThread {
|
||||
applyFilter(
|
||||
currentFilter,
|
||||
if (limitSearchToLinphoneAccounts) corePreferences.defaultDomain else "",
|
||||
MagicSearch.Source.Friends.toInt() or MagicSearch.Source.LdapServers.toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun exportContactAsVCard(friend: Friend) {
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
@ -251,26 +207,47 @@ class ContactsListViewModel @UiThread constructor() : AbstractTopBarViewModel()
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createFriendFromSearchResult(searchResult: SearchResult): Friend {
|
||||
val searchResultFriend = searchResult.friend
|
||||
if (searchResultFriend != null) return searchResultFriend
|
||||
private fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("$TAG Processing [${results.size}] results")
|
||||
|
||||
val friend = coreContext.core.createFriend()
|
||||
val list = arrayListOf<ContactAvatarModel>()
|
||||
val favouritesList = arrayListOf<ContactAvatarModel>()
|
||||
var count = 0
|
||||
|
||||
val address = searchResult.address
|
||||
if (address != null) {
|
||||
friend.address = address
|
||||
}
|
||||
for (result in results) {
|
||||
val friend = result.friend
|
||||
|
||||
val number = searchResult.phoneNumber
|
||||
if (number != null) {
|
||||
friend.addPhoneNumber(number)
|
||||
val model = if (friend != null) {
|
||||
coreContext.contactsManager.getContactAvatarModelForFriend(friend)
|
||||
} else {
|
||||
coreContext.contactsManager.getContactAvatarModelForAddress(result.address)
|
||||
}
|
||||
|
||||
if (address != null && address.username == number) {
|
||||
friend.removeAddress(address)
|
||||
list.add(model)
|
||||
count += 1
|
||||
|
||||
if (friend?.starred == true) {
|
||||
favouritesList.add(model)
|
||||
}
|
||||
|
||||
if (count == 20) {
|
||||
contactsList.postValue(list)
|
||||
fetchInProgress.postValue(false)
|
||||
}
|
||||
}
|
||||
|
||||
return friend
|
||||
val collator = Collator.getInstance(Locale.getDefault())
|
||||
favouritesList.sortWith { model1, model2 ->
|
||||
collator.compare(model1.friend.name, model2.friend.name)
|
||||
}
|
||||
list.sortWith { model1, model2 ->
|
||||
collator.compare(model1.friend.name, model2.friend.name)
|
||||
}
|
||||
|
||||
favourites.postValue(favouritesList)
|
||||
contactsList.postValue(list)
|
||||
fetchInProgress.postValue(false)
|
||||
|
||||
Log.i("$TAG Processed [${results.size}] results")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,9 +110,22 @@ class ContactsAndSuggestionsListAdapter :
|
|||
fun bind(contactOrSuggestionModel: ContactOrSuggestionModel) {
|
||||
with(binding) {
|
||||
model = contactOrSuggestionModel.avatarModel.value
|
||||
|
||||
setOnClickListener {
|
||||
contactClickedEvent.value = Event(contactOrSuggestionModel)
|
||||
}
|
||||
|
||||
val previousItem = bindingAdapterPosition - 1
|
||||
val previousLetter = if (previousItem >= 0) {
|
||||
getItem(previousItem).name[0].toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
val currentLetter = contactOrSuggestionModel.name[0].toString()
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
firstContactStartingByThatLetter = displayLetter
|
||||
|
||||
executePendingBindings()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import androidx.annotation.UiThread
|
|||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.text.Collator
|
||||
import java.util.Locale
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
|
|
@ -178,67 +180,6 @@ abstract class AddressSelectionViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("$TAG Processing [${results.size}] results")
|
||||
|
||||
val contactsList = arrayListOf<ContactOrSuggestionModel>()
|
||||
val suggestionsList = arrayListOf<ContactOrSuggestionModel>()
|
||||
var previousLetter = ""
|
||||
|
||||
for (result in results) {
|
||||
val address = result.address
|
||||
if (address != null) {
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
if (friend != null) {
|
||||
val model = ContactOrSuggestionModel(address, friend)
|
||||
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||
address
|
||||
)
|
||||
model.avatarModel.postValue(avatarModel)
|
||||
|
||||
val currentLetter = friend.name?.get(0).toString()
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
if (currentLetter != previousLetter) {
|
||||
previousLetter = currentLetter
|
||||
}
|
||||
avatarModel.firstContactStartingByThatLetter.postValue(
|
||||
displayLetter
|
||||
)
|
||||
|
||||
contactsList.add(model)
|
||||
} else {
|
||||
// If user-input generated result (always last) already exists, don't show it again
|
||||
if (result.sourceFlags == MagicSearch.Source.Request.toInt()) {
|
||||
val found = suggestionsList.find {
|
||||
it.address.weakEqual(address)
|
||||
}
|
||||
if (found != null) {
|
||||
Log.i(
|
||||
"$TAG Result generated from user input is a duplicate of an existing solution, preventing double"
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val model = ContactOrSuggestionModel(address) {
|
||||
coreContext.startCall(address)
|
||||
}
|
||||
|
||||
suggestionsList.add(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val list = arrayListOf<ContactOrSuggestionModel>()
|
||||
list.addAll(contactsList)
|
||||
list.addAll(suggestionsList)
|
||||
contactsAndSuggestionsList.postValue(list)
|
||||
Log.i(
|
||||
"$TAG Processed [${results.size}] results, extracted [${suggestionsList.size}] suggestions"
|
||||
)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyFilter(filter: String) {
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
@ -278,4 +219,63 @@ abstract class AddressSelectionViewModel @UiThread constructor() : ViewModel() {
|
|||
aggregation
|
||||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("$TAG Processing [${results.size}] results")
|
||||
|
||||
val contactsList = arrayListOf<ContactOrSuggestionModel>()
|
||||
val suggestionsList = arrayListOf<ContactOrSuggestionModel>()
|
||||
|
||||
for (result in results) {
|
||||
val address = result.address
|
||||
if (address != null) {
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
if (friend != null) {
|
||||
val model = ContactOrSuggestionModel(address, friend)
|
||||
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||
address
|
||||
)
|
||||
model.avatarModel.postValue(avatarModel)
|
||||
|
||||
contactsList.add(model)
|
||||
} else {
|
||||
// If user-input generated result (always last) already exists, don't show it again
|
||||
if (result.sourceFlags == MagicSearch.Source.Request.toInt()) {
|
||||
val found = suggestionsList.find {
|
||||
it.address.weakEqual(address)
|
||||
}
|
||||
if (found != null) {
|
||||
Log.i(
|
||||
"$TAG Result generated from user input is a duplicate of an existing solution, preventing double"
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val model = ContactOrSuggestionModel(address) {
|
||||
coreContext.startCall(address)
|
||||
}
|
||||
|
||||
suggestionsList.add(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val collator = Collator.getInstance(Locale.getDefault())
|
||||
contactsList.sortWith { model1, model2 ->
|
||||
collator.compare(model1.name, model2.name)
|
||||
}
|
||||
suggestionsList.sortWith { model1, model2 ->
|
||||
collator.compare(model1.name, model2.name)
|
||||
}
|
||||
|
||||
val list = arrayListOf<ContactOrSuggestionModel>()
|
||||
list.addAll(contactsList)
|
||||
list.addAll(suggestionsList)
|
||||
contactsAndSuggestionsList.postValue(list)
|
||||
Log.i(
|
||||
"$TAG Processed [${results.size}] results, extracted [${suggestionsList.size}] suggestions"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
<variable
|
||||
name="onLongClickListener"
|
||||
type="View.OnLongClickListener" />
|
||||
<variable
|
||||
name="firstContactStartingByThatLetter"
|
||||
type="Boolean" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
|
@ -45,7 +48,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@{model.firstLetter, default=`A`}"
|
||||
android:visibility="@{model.firstContactStartingByThatLetter ? View.VISIBLE : View.INVISIBLE}"
|
||||
android:visibility="@{firstContactStartingByThatLetter ? View.VISIBLE : View.INVISIBLE}"
|
||||
android:textColor="@color/gray_main2_400"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue