Improved avatars cache

This commit is contained in:
Sylvain Berfini 2023-11-23 10:35:26 +01:00
parent 56bc96314a
commit 20fbeda124
3 changed files with 57 additions and 16 deletions

View file

@ -61,7 +61,8 @@ class ContactsManager @UiThread constructor() {
private val listeners = arrayListOf<ContactsListener>()
private val avatarsMap = hashMapOf<String, ContactAvatarModel>()
private val knownContactsAvatarsMap = hashMapOf<String, ContactAvatarModel>()
private val unknownContactsAvatarsMap = hashMapOf<String, ContactAvatarModel>()
private val friendListListener: FriendListListenerStub = object : FriendListListenerStub() {
@WorkerThread
@ -70,8 +71,9 @@ class ContactsManager @UiThread constructor() {
"$TAG Presence received for list [${list.displayName}] and [${friends.size}] friends, cleaning avatars map"
)
avatarsMap.values.forEach(ContactAvatarModel::destroy)
avatarsMap.clear()
// Do not clear the already known contacts avatars!
unknownContactsAvatarsMap.values.forEach(ContactAvatarModel::destroy)
unknownContactsAvatarsMap.clear()
for (listener in listeners) {
listener.onContactsLoaded()
@ -130,8 +132,10 @@ class ContactsManager @UiThread constructor() {
nativeContactsLoaded = true
Log.i("$TAG Native contacts have been loaded, cleaning avatars map")
avatarsMap.values.forEach(ContactAvatarModel::destroy)
avatarsMap.clear()
knownContactsAvatarsMap.values.forEach(ContactAvatarModel::destroy)
knownContactsAvatarsMap.clear()
unknownContactsAvatarsMap.values.forEach(ContactAvatarModel::destroy)
unknownContactsAvatarsMap.clear()
notifyContactsListChanged()
}
@ -210,7 +214,7 @@ class ContactsManager @UiThread constructor() {
clone.clean()
val key = clone.asStringUriOnly()
val foundInMap = if (avatarsMap.keys.contains(key)) avatarsMap[key] else null
val foundInMap = getAvatarModelFromCache(key)
if (foundInMap != null) {
Log.i("$TAG Avatar model found in map for SIP URI [$key]")
return foundInMap
@ -225,24 +229,28 @@ class ContactsManager @UiThread constructor() {
fakeFriend.address = clone
fakeFriend.name = LinphoneUtils.getDisplayName(localAccount.params.identityAddress)
fakeFriend.photo = localAccount.params.pictureUri
ContactAvatarModel(fakeFriend)
val model = ContactAvatarModel(fakeFriend)
unknownContactsAvatarsMap[key] = model
model
} else {
Log.i("$TAG Looking for friend matching SIP URI [$key]")
val friend = coreContext.contactsManager.findContactByAddress(clone)
if (friend != null) {
Log.i("$TAG Matching friend [${friend.name}] found for SIP URI [$key]")
ContactAvatarModel(friend)
val model = ContactAvatarModel(friend)
knownContactsAvatarsMap[key] = model
model
} else {
Log.i("$TAG No matching friend found for SIP URI [$key]...")
val fakeFriend = coreContext.core.createFriend()
fakeFriend.name = LinphoneUtils.getDisplayName(address)
fakeFriend.address = clone
ContactAvatarModel(fakeFriend)
val model = ContactAvatarModel(fakeFriend)
unknownContactsAvatarsMap[key] = model
model
}
}
avatarsMap[key] = avatar
return avatar
}
@ -264,7 +272,7 @@ class ContactsManager @UiThread constructor() {
clone.clean()
val key = clone.asStringUriOnly()
val foundInMap = if (avatarsMap.keys.contains(key)) avatarsMap[key] else null
val foundInMap = getAvatarModelFromCache(key)
if (foundInMap != null) {
Log.i("$TAG Found avatar model in map using SIP URI [$key]")
return foundInMap
@ -272,7 +280,7 @@ class ContactsManager @UiThread constructor() {
Log.w("$TAG Avatar model not found in map with SIP URI [$key]")
val avatar = ContactAvatarModel(friend)
avatarsMap[key] = avatar
knownContactsAvatarsMap[key] = avatar
return avatar
}
@ -286,11 +294,11 @@ class ContactsManager @UiThread constructor() {
return ContactAvatarModel(fakeFriend)
}
val foundInMap = if (avatarsMap.keys.contains(key)) avatarsMap[key] else null
val foundInMap = getAvatarModelFromCache(key)
if (foundInMap != null) return foundInMap
val avatar = LinphoneUtils.getAvatarModelForConferenceInfo(conferenceInfo)
avatarsMap[key] = avatar
unknownContactsAvatarsMap[key] = avatar
return avatar
}
@ -437,6 +445,11 @@ class ContactsManager @UiThread constructor() {
return personBuilder.build()
}
@WorkerThread
private fun getAvatarModelFromCache(key: String): ContactAvatarModel? {
return knownContactsAvatarsMap[key] ?: unknownContactsAvatarsMap[key]
}
interface ContactsListener {
fun onContactsLoaded()
}

View file

@ -138,7 +138,7 @@ class MainActivity : AppCompatActivity() {
it.consume { error ->
val tag = "DEFAULT_ACCOUNT_REGISTRATION_ERROR"
if (error) {
// First remove any already existing connection error toat
// First remove any already existing connection error toast
removePersistentRedToast(tag)
val message = getString(R.string.toast_default_account_connection_state_error)

View file

@ -170,6 +170,27 @@ class MainViewModel @UiThread constructor() : ViewModel() {
else -> {}
}
}
@WorkerThread
override fun onDefaultAccountChanged(core: Core, account: Account) {
Log.i(
"$TAG Default account changed, now is [${account.params.identityAddress?.asStringUriOnly()}]"
)
removeAlert(NON_DEFAULT_ACCOUNT_NOTIFICATIONS)
if (defaultAccountRegistrationFailed && account.state != RegistrationState.Failed) {
Log.i(
"$TAG Newly set default account isn't in failed registration state, clearing alert"
)
defaultAccountRegistrationFailed = false
defaultAccountRegistrationErrorEvent.postValue(Event(false))
// Refresh REGISTER to re-compute alerts regarding accounts registration state
core.refreshRegisters()
}
// TODO: compute other calls notifications count
}
}
init {
@ -204,6 +225,13 @@ class MainViewModel @UiThread constructor() : ViewModel() {
@UiThread
fun closeTopBar() {
showAlert.value = false
coreContext.postOnCoreThread {
Log.i("$TAG User closed alerts top bar, clearing alerts")
cancelAlertJob()
alertsList.clear()
updateDisplayedAlert()
}
}
@UiThread