Skip to content
Snippets Groups Projects
Commit c5e15d26 authored by Sébastien Blin's avatar Sébastien Blin
Browse files

contactmodel: cache profiles for non contacts profile

If we're a member of a group swarm, we will receive profiles from
non contact (the other members of a conversation).
This patch try to get from cache before calling getContact() to be
able to retrieve profiles from non contacts if stored by the daemon

Change-Id: I864f1d5dd9f65232751e170b930606d23241d283
parent 77e019b0
No related branches found
No related tags found
No related merge requests found
......@@ -420,8 +420,14 @@ Utils::contactPhoto(LRCInstance* instance,
try {
auto& accInfo = instance->accountModel().getAccountInfo(
accountId.isEmpty() ? instance->get_currentAccountId() : accountId);
auto contactInfo = accInfo.contactModel->getContact(contactUri);
auto contactPhoto = accInfo.contactModel->avatar(contactUri);
if (!contactPhoto.isEmpty()) {
photo = imageFromBase64String(contactPhoto);
if (!photo.isNull())
return Utils::scaleAndFrame(photo, size);
}
// If no avatar is found, generate one
auto contactInfo = accInfo.contactModel->getContact(contactUri);
auto bestName = accInfo.contactModel->bestNameForContact(contactUri);
if (accInfo.profileInfo.type == profile::Type::SIP
&& contactInfo.profileInfo.type == profile::Type::TEMPORARY) {
......@@ -429,12 +435,6 @@ Utils::contactPhoto(LRCInstance* instance,
} else if (contactInfo.profileInfo.type == profile::Type::TEMPORARY
&& contactInfo.profileInfo.uri.isEmpty()) {
photo = Utils::fallbackAvatar(QString(), QString());
} else if (!contactPhoto.isEmpty()) {
photo = imageFromBase64String(contactPhoto);
if (photo.isNull()) {
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
photo = Utils::fallbackAvatar("jami:" + contactInfo.profileInfo.uri, avatarName);
}
} else {
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
photo = Utils::fallbackAvatar("jami:" + contactInfo.profileInfo.uri, avatarName);
......
......@@ -133,6 +133,8 @@ public:
// Store if a profile is cached for a given URI.
QSet<QString> cachedProfiles;
// For non contacts (such as members of a group)
QMap<QString, profile::Info> cachedProfilesInfo;
public Q_SLOTS:
/**
......@@ -557,10 +559,9 @@ ContactModel::bestNameForContact(const QString& contactUri) const
return owner.accountModel->bestNameForAccount(owner.id);
QString res = contactUri;
try {
auto contact = getContact(contactUri);
auto alias = displayName(contactUri).simplified();
if (alias.isEmpty()) {
return bestIdFromContactInfo(contact);
return bestIdFromContactInfo(getContact(contactUri));
}
return alias;
} catch (const std::out_of_range&) {
......@@ -1184,17 +1185,12 @@ ContactModelPimpl::slotProfileReceived(const QString& accountId,
return;
}
// Make sure this is for a contact and not the linked account,
// then just remove the URI from the cache list and notify.
std::lock_guard<std::mutex> lk(contactsMtx_);
if (contacts.find(peer) != contacts.end()) {
// Remove the URI from the cache list and notify.
cachedProfiles.remove(peer);
// This signal should be listened to in order to update contact display names
// and avatars in the client.
Q_EMIT linked.profileUpdated(peer);
}
}
void
ContactModelPimpl::slotUserSearchEnded(const QString& accountId,
......@@ -1236,30 +1232,45 @@ ContactModelPimpl::slotUserSearchEnded(const QString& accountId,
template<typename Func>
QString
ContactModelPimpl::getCachedProfileProperty(const QString& contactUri, Func extractor)
ContactModelPimpl::getCachedProfileProperty(const QString& peerUri, Func extractor)
{
std::lock_guard<std::mutex> lk(contactsMtx_);
// For search results it's loaded and not in storage yet.
if (searchResult.contains(contactUri)) {
auto contact = searchResult.value(contactUri);
if (searchResult.contains(peerUri)) {
auto contact = searchResult.value(peerUri);
return extractor(contact.profileInfo);
}
// Try to find the contact.
auto it = contacts.find(contactUri);
if (it == contacts.end()) {
return {};
auto it = contacts.find(peerUri);
auto isContact = it != contacts.end();
auto getPInfo = [&]() -> profile::Info& {
if (!isContact) {
auto itNonContact = cachedProfilesInfo.find(peerUri);
if (itNonContact != cachedProfilesInfo.end()) {
return *itNonContact;
} else {
profile::Info pInfo;
pInfo.uri = peerUri;
pInfo.type = profile::Type::TEMPORARY;
cachedProfilesInfo.insert(peerUri, pInfo);
return cachedProfilesInfo[peerUri];
}
} else {
return it->profileInfo;
}
};
profile::Info& pInfo = getPInfo();
// If we have a profile that appears to be recently cached, return the extracted property.
if (cachedProfiles.contains(contactUri)) {
return extractor(it->profileInfo);
if (cachedProfiles.contains(peerUri)) {
return extractor(pInfo);
}
// Otherwise, update the profile info and return the extracted property.
updateCachedProfile(it->profileInfo);
updateCachedProfile(pInfo);
return extractor(it->profileInfo);
return extractor(pInfo);
}
} // namespace lrc
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment