From e0b146039f3b561e57bef6c6d1c7a61a0dd8be0a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 13 Sep 2023 15:47:50 +0200 Subject: [PATCH] Refresh friend after edition + limit native contacts refresh to 1 per minute --- .../org/linphone/contacts/ContactLoader.kt | 12 ++- .../main/contacts/model/ContactDeviceModel.kt | 3 +- .../contacts/viewmodel/ContactViewModel.kt | 99 +++++++++++++------ .../layout/contact_new_or_edit_fragment.xml | 1 - 4 files changed, 79 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/linphone/contacts/ContactLoader.kt b/app/src/main/java/org/linphone/contacts/ContactLoader.kt index 59e2c93a4..627f30c56 100644 --- a/app/src/main/java/org/linphone/contacts/ContactLoader.kt +++ b/app/src/main/java/org/linphone/contacts/ContactLoader.kt @@ -54,6 +54,8 @@ class ContactLoader : LoaderManager.LoaderCallbacks { private const val NATIVE_ADDRESS_BOOK_FRIEND_LIST = "Native address-book" const val LINPHONE_ADDRESS_BOOK_FRIEND_LIST = "Linphone address-book" + + private const val MAX_INTERVAL_TO_REFRESH = 60000L } @MainThread @@ -69,7 +71,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE ) - return CursorLoader( + val loader = CursorLoader( coreContext.context, ContactsContract.Data.CONTENT_URI, projection, @@ -77,6 +79,10 @@ class ContactLoader : LoaderManager.LoaderCallbacks { selectionArgs, ContactsContract.Data.CONTACT_ID + " ASC" ) + + loader.setUpdateThrottle(MAX_INTERVAL_TO_REFRESH) // Update at most once per minute + + return loader } @MainThread @@ -293,6 +299,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { Log.w("$TAG No friend created!") } else { Log.i("$TAG ${friends.size} friends created") + val fetchedFriends = friends.values val fl = core.getFriendListByName(NATIVE_ADDRESS_BOOK_FRIEND_LIST) ?: core.createFriendList() if (fl.displayName.isNullOrEmpty()) { @@ -311,8 +318,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { } } - val friendsList = friends.values - for (friend in friendsList) { + for (friend in fetchedFriends) { fl.addLocalFriend(friend) } friends.clear() diff --git a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt index 9360d7120..ce391f6ea 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/model/ContactDeviceModel.kt @@ -20,8 +20,9 @@ package org.linphone.ui.main.contacts.model import androidx.annotation.UiThread +import androidx.annotation.WorkerThread -class ContactDeviceModel @UiThread constructor( +class ContactDeviceModel @WorkerThread constructor( val name: String, val trusted: Boolean, private val onCall: ((model: ContactDeviceModel) -> Unit)? = null diff --git a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt index c66f62e0c..e506da868 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactViewModel.kt @@ -20,6 +20,7 @@ package org.linphone.ui.main.contacts.viewmodel import androidx.annotation.UiThread +import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -27,6 +28,7 @@ import java.io.File import java.util.Locale import kotlinx.coroutines.launch import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.contacts.ContactsManager import org.linphone.contacts.getListOfSipAddressesAndPhoneNumbers import org.linphone.core.Friend import org.linphone.core.tools.Log @@ -114,57 +116,92 @@ class ContactViewModel @UiThread constructor() : ViewModel() { } } + private val contactsListener = object : ContactsManager.ContactsListener { + @WorkerThread + override fun onContactsLoaded() { + val friend = coreContext.contactsManager.findContactById(refKey) + if (friend != null && friend != this@ContactViewModel.friend) { + Log.i( + "$TAG Found contact [${friend.name}] matching ref key [$refKey] after contacts have been loaded/updated" + ) + this@ContactViewModel.friend = friend + refreshContactInfo() + } + } + } + private lateinit var friend: Friend + private var refKey: String = "" + init { expandNumbersAndAddresses.value = true expandDevicesTrust.value = false // TODO FIXME: set it to true when it will work for real + + coreContext.postOnCoreThread { + coreContext.contactsManager.addListener(contactsListener) + } + } + + override fun onCleared() { + super.onCleared() + + coreContext.postOnCoreThread { + coreContext.contactsManager.removeListener(contactsListener) + } } @UiThread fun findContactByRefKey(refKey: String) { + this.refKey = refKey + coreContext.postOnCoreThread { val friend = coreContext.contactsManager.findContactById(refKey) if (friend != null) { Log.i("$TAG Found contact [${friend.name}] matching ref key [$refKey]") this.friend = friend - isFavourite.postValue(friend.starred) - - contact.postValue(ContactAvatarModel(friend)) - - val organization = friend.organization - if (!organization.isNullOrEmpty()) { - company.postValue(organization!!) - } - val jobTitle = friend.jobTitle - if (!jobTitle.isNullOrEmpty()) { - title.postValue(jobTitle!!) - } - - val addressesAndNumbers = friend.getListOfSipAddressesAndPhoneNumbers(listener) - sipAddressesAndPhoneNumbers.postValue(addressesAndNumbers) - - val devicesList = arrayListOf() - // TODO FIXME: use real devices list from API - devicesList.add(ContactDeviceModel("Pixel 6 Pro de Sylvain", true)) - devicesList.add(ContactDeviceModel("Sylvain Galaxy Tab S9 Pro+ Ultra", true)) - devicesList.add( - ContactDeviceModel("MacBook Pro de Marcel", false) { - // TODO: check if do not show dialog anymore setting is set - if (::friend.isInitialized) { - startCallToDeviceToIncreaseTrustEvent.value = - Event(Pair(friend.name.orEmpty(), it.name)) - } - } - ) - devicesList.add(ContactDeviceModel("sylvain@fedora-linux-38", true)) - devices.postValue(devicesList) + refreshContactInfo() contactFoundEvent.postValue(Event(true)) } } } + @WorkerThread + fun refreshContactInfo() { + isFavourite.postValue(friend.starred) + + contact.postValue(ContactAvatarModel(friend)) + + val organization = friend.organization + if (!organization.isNullOrEmpty()) { + company.postValue(organization!!) + } + val jobTitle = friend.jobTitle + if (!jobTitle.isNullOrEmpty()) { + title.postValue(jobTitle!!) + } + + val addressesAndNumbers = friend.getListOfSipAddressesAndPhoneNumbers(listener) + sipAddressesAndPhoneNumbers.postValue(addressesAndNumbers) + + val devicesList = arrayListOf() + // TODO FIXME: use real devices list from API + devicesList.add(ContactDeviceModel("Pixel 6 Pro de Sylvain", true)) + devicesList.add(ContactDeviceModel("Sylvain Galaxy Tab S9 Pro+ Ultra", true)) + devicesList.add( + ContactDeviceModel("MacBook Pro de Marcel", false) { + // TODO: check if do not show dialog anymore setting is set + if (::friend.isInitialized) { + startCallToDeviceToIncreaseTrustEvent.value = + Event(Pair(friend.name.orEmpty(), it.name)) + } + } + ) + devicesList.add(ContactDeviceModel("sylvain@fedora-linux-38", true)) + devices.postValue(devicesList) + } + @UiThread fun toggleNumbersAndAddressesExpand() { expandNumbersAndAddresses.value = expandNumbersAndAddresses.value == false diff --git a/app/src/main/res/layout/contact_new_or_edit_fragment.xml b/app/src/main/res/layout/contact_new_or_edit_fragment.xml index 1576b6d51..ef330e96d 100644 --- a/app/src/main/res/layout/contact_new_or_edit_fragment.xml +++ b/app/src/main/res/layout/contact_new_or_edit_fragment.xml @@ -68,7 +68,6 @@ android:id="@+id/scrollView" android:layout_width="0dp" android:layout_height="0dp" - android:background="@color/gray_7" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/title"