From 0be264884958228af5294a27ab09680880ba294a Mon Sep 17 00:00:00 2001 From: blue Date: Wed, 31 Jan 2024 20:22:49 -0300 Subject: [PATCH] Now avatars are properly autogenerated, reduced vCard spam --- core/account.cpp | 17 ++++---- core/conference.cpp | 70 +++++++++++++-------------------- core/conference.h | 23 ++++++----- core/contact.cpp | 7 ++-- core/handlers/rosterhandler.cpp | 36 ++++++++--------- core/rosteritem.h | 5 +-- external/lmdbal | 2 +- external/qxmpp | 2 +- ui/models/roster.cpp | 6 +-- 9 files changed, 76 insertions(+), 92 deletions(-) diff --git a/core/account.cpp b/core/account.cpp index 858c177..8082aeb 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -367,19 +367,23 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) { vh->handlePresenceOfMyAccountChange(p_presence); } else { RosterItem* item = rh->getRosterItem(jid); - if (item != nullptr) - item->handlePresence(p_presence); + if (item != nullptr) { + if (item->isMuc()) //MUC presence is handled by inner muc events + return; + else + item->handlePresence(p_presence); + } } switch (p_presence.type()) { case QXmppPresence::Error: qDebug() << "An error reported by presence from" << id << p_presence.error().text(); break; - case QXmppPresence::Available:{ + case QXmppPresence::Available: { QDateTime lastInteraction = p_presence.lastUserInteraction(); - if (!lastInteraction.isValid()) { + if (!lastInteraction.isValid()) lastInteraction = QDateTime::currentDateTimeUtc(); - } + emit addPresence(jid, resource, { {"lastActivity", lastInteraction}, {"availability", p_presence.availableStatusType()}, //TODO check and handle invisible @@ -392,8 +396,7 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) { ) } }); - } - break; + } break; case QXmppPresence::Unavailable: emit removePresence(jid, resource); break; diff --git a/core/conference.cpp b/core/conference.cpp index 3904675..48331e9 100644 --- a/core/conference.cpp +++ b/core/conference.cpp @@ -132,9 +132,8 @@ void Core::Conference::onRoomParticipantAdded(const QString& p_name) { if (resource.size() > 0) { QDateTime lastInteraction = pres.lastUserInteraction(); - if (!lastInteraction.isValid()) { + if (!lastInteraction.isValid()) lastInteraction = QDateTime::currentDateTimeUtc(); - } QMap cData = { {"lastActivity", lastInteraction}, @@ -153,29 +152,37 @@ void Core::Conference::onRoomParticipantAdded(const QString& p_name) { careAboutAvatar(hasAvatar, itr->second, cData, resource, p_name); emit addParticipant(resource, cData); + + if (!hasAvatar) // because this way vCard is already requested, no need to handle possible avatar update + return; } - + handlePossibleAvatarUpdate(pres, resource, hasAvatar, itr->second); +} + +void Core::Conference::handlePossibleAvatarUpdate ( + const QXmppPresence& pres, + const QString& resource, + bool hasAvatar, + const Archive::AvatarInfo& info +) { switch (pres.vCardUpdateType()) { case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo break; case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here break; - case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any - if (!hasAvatar || !itr->second.autogenerated) { + case QXmppPresence::VCardUpdateNoPhoto: //there is no photo, need to drop if any + if (!hasAvatar || !info.autogenerated) setAutoGeneratedAvatar(resource); - } - } - break; - case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load - if (hasAvatar) { - if (itr->second.autogenerated || itr->second.hash != pres.photoHash()) - emit requestVCard(p_name); + break; + case QXmppPresence::VCardUpdateValidPhoto: //there is a photo, need to load + if (hasAvatar) { + if (info.autogenerated || info.hash != pres.photoHash()) + emit requestVCard(pres.from()); } else { - emit requestVCard(p_name); + emit requestVCard(pres.from()); } break; - } } } @@ -235,32 +242,10 @@ void Core::Conference::handlePresence(const QXmppPresence& pres) { QString resource(""); if (comps.size() > 1) resource = comps.back(); - - switch (pres.vCardUpdateType()) { - case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo - break; - case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here - break; - case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any - Archive::AvatarInfo info; - bool hasAvatar = readAvatarInfo(info, resource); - if (!hasAvatar || !info.autogenerated) { - setAutoGeneratedAvatar(resource); - } - } - break; - case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load - Archive::AvatarInfo info; - bool hasAvatar = readAvatarInfo(info, resource); - if (hasAvatar) { - if (info.autogenerated || info.hash != pres.photoHash()) - emit requestVCard(id); - } else { - emit requestVCard(id); - } - break; - } - } + + Archive::AvatarInfo info; + bool hasAvatar = readAvatarInfo(info, resource); + handlePossibleAvatarUpdate(pres, resource, hasAvatar, info); } bool Core::Conference::setAutoGeneratedAvatar(const QString& resource) { @@ -272,6 +257,7 @@ bool Core::Conference::setAutoGeneratedAvatar(const QString& resource) { exParticipants.insert(std::make_pair(resource, newInfo)); else itr->second = newInfo; + emit changeParticipant(resource, { {"avatarState", static_cast(Shared::Avatar::autocreated)}, {"avatarPath", avatarPath(resource) + "." + newInfo.type} @@ -313,18 +299,18 @@ bool Core::Conference::setAvatar(const QByteArray& data, Archive::AvatarInfo& in void Core::Conference::handleResponseVCard(const QXmppVCardIq& card, const QString &resource, Shared::VCard& out) { RosterItem::handleResponseVCard(card, resource, out); - if (resource.size() > 0) { + if (resource.size() > 0) emit changeParticipant(resource, { {"avatarState", static_cast(out.getAvatarType())}, {"avatarPath", out.getAvatarPath()} }); - } } QMap Core::Conference::getAllAvatars() const { QMap result; for (const std::pair& pair : exParticipants) result.insert(pair.first, avatarPath(pair.first) + "." + pair.second.type); + return result; } diff --git a/core/conference.h b/core/conference.h index 3c077e3..501738b 100644 --- a/core/conference.h +++ b/core/conference.h @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -#ifndef CORE_CONFERENCE_H -#define CORE_CONFERENCE_H +#pragma once #include @@ -29,14 +28,8 @@ #include #include -namespace Core -{ - -/** - * @todo write docs - */ -class Conference : public RosterItem -{ +namespace Core { +class Conference : public RosterItem { Q_OBJECT public: Conference(const QString& p_jid, const QString& p_account, bool p_autoJoin, const QString& p_name, const QString& p_nick, QXmppMucRoom* p_room); @@ -69,6 +62,14 @@ signals: protected: bool setAvatar(const QByteArray &data, Archive::AvatarInfo& info, const QString &resource = "") override; +private: + void handlePossibleAvatarUpdate( + const QXmppPresence& pres, + const QString& resource, + bool hasAvatar, + const Archive::AvatarInfo& info + ); + private: QString nick; QXmppMucRoom* room; @@ -91,5 +92,3 @@ private slots: }; } - -#endif // CORE_CONFERENCE_H diff --git a/core/contact.cpp b/core/contact.cpp index f18dae3..aef637b 100644 --- a/core/contact.cpp +++ b/core/contact.cpp @@ -73,18 +73,17 @@ void Core::Contact::handlePresence(const QXmppPresence& pres) { case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any Archive::AvatarInfo info; bool hasAvatar = readAvatarInfo(info); - if (!hasAvatar || !info.autogenerated) { + if (!hasAvatar || !info.autogenerated) setAutoGeneratedAvatar(); - } + } break; case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load Archive::AvatarInfo info; bool hasAvatar = readAvatarInfo(info); if (hasAvatar) { - if (info.autogenerated || info.hash != pres.photoHash()) { + if (info.autogenerated || info.hash != pres.photoHash()) emit requestVCard(jid); - } } else { emit requestVCard(jid); } diff --git a/core/handlers/rosterhandler.cpp b/core/handlers/rosterhandler.cpp index 940ddbf..e3020c8 100644 --- a/core/handlers/rosterhandler.cpp +++ b/core/handlers/rosterhandler.cpp @@ -98,13 +98,13 @@ void Core::RosterHandler::addedAccount(const QString& jid) { contact->setName(re.name()); if (newContact) { + handleNewContact(contact); QMap cData = contact->getInfo(); #if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0) cData.insert("trust", QVariant::fromValue(acc->th->getSummary(jid))); #endif int grCount = 0; - for (QSet::const_iterator itr = gr.begin(), end = gr.end(); itr != end; ++itr) { - const QString& groupName = *itr; + for (const QString& groupName : gr) { addToGroup(jid, groupName); emit acc->addContact(jid, groupName, cData); grCount++; @@ -117,7 +117,6 @@ void Core::RosterHandler::addedAccount(const QString& jid) { acc->dm->requestInfo(jid); //acc->dm->requestItems(jid); } - handleNewContact(contact); } } @@ -495,22 +494,23 @@ void Core::RosterHandler::removeContactFromGroupRequest(const QString& jid, cons if (itr == contacts.end()) { qDebug() << "An attempt to remove non existing contact" << lcJid << "of account" << acc->name << "from the group" << groupName << ", skipping"; + return; + } + + QXmppRosterIq::Item item = acc->rm->getRosterEntry(lcJid); + QSet groups = item.groups(); + QSet::const_iterator gItr = groups.find(groupName); + if (gItr != groups.end()) { + groups.erase(gItr); + item.setGroups(groups); + + QXmppRosterIq iq; + iq.setType(QXmppIq::Set); + iq.addItem(item); + acc->client.sendPacket(iq); } else { - QXmppRosterIq::Item item = acc->rm->getRosterEntry(lcJid); - QSet groups = item.groups(); - QSet::const_iterator gItr = groups.find(groupName); - if (gItr != groups.end()) { - groups.erase(gItr); - item.setGroups(groups); - - QXmppRosterIq iq; - iq.setType(QXmppIq::Set); - iq.addItem(item); - acc->client.sendPacket(iq); - } else { - qDebug() << "An attempt to remove contact" << lcJid << "of account" - << acc->name << "from the group" << groupName << "but it's not in that group, skipping"; - } + qDebug() << "An attempt to remove contact" << lcJid << "of account" + << acc->name << "from the group" << groupName << "but it's not in that group, skipping"; } } diff --git a/core/rosteritem.h b/core/rosteritem.h index 203ed88..33a08f0 100644 --- a/core/rosteritem.h +++ b/core/rosteritem.h @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -#ifndef CORE_ROSTERITEM_H -#define CORE_ROSTERITEM_H +#pragma once #include #include @@ -130,5 +129,3 @@ private: }; } - -#endif // CORE_ROSTERITEM_H diff --git a/external/lmdbal b/external/lmdbal index c83369f..79240aa 160000 --- a/external/lmdbal +++ b/external/lmdbal @@ -1 +1 @@ -Subproject commit c83369f34761e7a053d62312bd07fe5b3db3a519 +Subproject commit 79240aa5354e9fa9d09d3b12ea1077a81bb90809 diff --git a/external/qxmpp b/external/qxmpp index 8dda3c9..0cd7379 160000 --- a/external/qxmpp +++ b/external/qxmpp @@ -1 +1 @@ -Subproject commit 8dda3c9921c34b9e33883b0d140e8de12edc0736 +Subproject commit 0cd7379bd78aa01af7e84f2fad6269ef0c0ba49c diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index 0f35baa..fc6382a 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -650,10 +650,10 @@ void Models::Roster::onChildRemoved() { void Models::Roster::addPresence(const QString& account, const QString& jid, const QString& name, const QMap& data) { ElId contactId(account, jid); std::map::iterator itr = contacts.find(contactId); - if (itr != contacts.end()) { + if (itr != contacts.end()) itr->second->addPresence(name, data); - } - + else + qDebug() << "Received a presence" << jid + "/" + name << "don't know what to do with it"; } void Models::Roster::removePresence(const QString& account, const QString& jid, const QString& name) {