Skip to content

Commit

Permalink
Current version of Psi+ is 1.5.1964
Browse files Browse the repository at this point in the history
It is based on:
* psi: d2e744ac
* plugins: 7a65467
* psimedia: 478567e
* resources: e32ef4b
  • Loading branch information
tehnick committed Jun 12, 2024
1 parent 0bcc7be commit a87ae2f
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 40 deletions.
2 changes: 1 addition & 1 deletion iris/src/xmpp/xmpp-im/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void Client::setCapsOptimizationAllowed(bool allowed) { d->capsOptimization = al

bool Client::capsOptimizationAllowed() const
{
if (d->capsOptimization && d->active && d->serverInfoManager->server_features().hasCapsOptimize()) {
if (d->capsOptimization && d->active && d->serverInfoManager->serverFeatures().hasCapsOptimize()) {
auto it = d->resourceList.find(d->resource);
return it != d->resourceList.end() && it->status().isAvailable();
}
Expand Down
2 changes: 1 addition & 1 deletion iris/src/xmpp/xmpp-im/xmpp_externalservicediscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ ExternalServiceDiscovery::ExternalServiceDiscovery(Client *client) : client_(cli

bool ExternalServiceDiscovery::isSupported() const
{
return client_->serverInfoManager()->server_features().test("urn:xmpp:extdisco:2");
return client_->serverInfoManager()->serverFeatures().test("urn:xmpp:extdisco:2");
}

void ExternalServiceDiscovery::services(QObject *ctx, ServicesCallback &&callback, std::chrono::minutes minTtl,
Expand Down
8 changes: 4 additions & 4 deletions iris/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,12 @@ void ServerInfoManager::server_disco_finished()
{
JT_DiscoInfo *jt = static_cast<JT_DiscoInfo *>(sender());
if (jt->success()) {
_server_features = jt->item().features();
_serverFeatures = jt->item().features();

if (_server_features.hasMulticast())
if (_serverFeatures.hasMulticast())
_multicastService = _client->jid().domain();

_canMessageCarbons = _server_features.hasMessageCarbons();
_canMessageCarbons = _serverFeatures.hasMessageCarbons();

auto servInfo
= jt->item().findExtension(XData::Data_Result, QLatin1String("http://jabber.org/network/serverinfo"));
Expand Down Expand Up @@ -297,7 +297,7 @@ void ServerInfoManager::account_disco_finished()
}
}
_hasPersistentStorage = jt->item().hasPersistentStorage();
_account_features = jt->item().features();
_accountFeatures = jt->item().features();

emit featuresChanged();
}
Expand Down
8 changes: 4 additions & 4 deletions iris/src/xmpp/xmpp-im/xmpp_serverinfomanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class ServerInfoManager : public QObject {
const QString &multicastService() const;
inline bool hasPEP() const { return _hasPEP; }
inline bool hasPersistentStorage() const { return _hasPersistentStorage; }
inline const Features &server_features() const { return _server_features; }
inline const Features &account_features() const { return _account_features; }
inline const Features &serverFeatures() const { return _serverFeatures; }
inline const Features &accountFeatures() const { return _accountFeatures; }
bool canMessageCarbons() const;
inline const QMap<QString, QStringList> &extraServerInfo() const { return _extraServerInfo; }

Expand Down Expand Up @@ -128,8 +128,8 @@ private slots:
private:
XMPP::Client *_client = nullptr;
CapsSpec _caps;
Features _server_features;
Features _account_features;
Features _serverFeatures;
Features _accountFeatures;
QString _multicastService;
QMap<QString, QStringList> _extraServerInfo; // XEP-0128, XEP-0157

Expand Down
4 changes: 4 additions & 0 deletions iris/src/xmpp/xmpp-im/xmpp_vcard4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ UriValue::UriValue(const QString &uri)
}
}

UriValue::UriValue(const QByteArray &data, const QString &mime) : data(data), mediaType(mime) { }

QString UriValue::toString() const
{
if (!mediaType.isEmpty()) {
Expand Down Expand Up @@ -633,6 +635,8 @@ VCard &VCard::operator=(const VCard &other)
return *this;
}

void VCard::detach() { d.detach(); }

VCard::VCard(const QDomElement &element) : d(new VCardData(element)) { }

VCard::~VCard() = default;
Expand Down
2 changes: 2 additions & 0 deletions iris/src/xmpp/xmpp-im/xmpp_vcard4.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class UriValue {
public:
UriValue() = default;
explicit UriValue(const QString &uri);
explicit UriValue(const QByteArray &data, const QString &mime);
QString toString() const;
inline operator QString() const { return toString(); }
bool isEmpty() const { return url.isEmpty() && data.isEmpty(); }
Expand Down Expand Up @@ -252,6 +253,7 @@ class VCard {
~VCard();

VCard &operator=(const VCard &);
void detach();

bool isEmpty() const;

Expand Down
52 changes: 29 additions & 23 deletions src/avatars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ AvatarFactory::AvatarFactory(PsiAccount *pa) : d(new Private)

connect(d->pa_->client(), &XMPP::Client::resourceAvailable, this, [this](const Jid &jid, const Resource &r) {
if (jid.compare(d->pa_->jid(), false)) {
return; // to avoid
return; // to avoid endless recursion with vcard update
}
statusUpdate(jid.withResource(QString()), r.status());
});
Expand Down Expand Up @@ -954,31 +954,37 @@ AvatarFactory::UserHashes AvatarFactory::userHashes(const Jid &jid) const
void AvatarFactory::setSelfAvatar(const QString &fileName)
{
if (!fileName.isEmpty()) {
QImage image(fileName);
if (!image.isNull()) {
// Publish data

QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
auto maxSz = maxAvatarSize();
image.scaled(image.size().boundedTo(QSize(maxSz, maxSz)), Qt::KeepAspectRatio, Qt::SmoothTransformation)
.save(&buffer, "PNG", 0);
auto hash = QCryptographicHash::hash(data, QCryptographicHash::Sha1);
QString id = QString::fromLatin1(hash.toHex());

QDomDocument *doc = account()->client()->doc();
QDomElement el = doc->createElementNS(PEP_AVATAR_DATA_NS, PEP_AVATAR_DATA_TN);
el.appendChild(doc->createTextNode(QString::fromLatin1(data.toBase64())));
d->selfAvatarData_ = data;
d->selfAvatarHash_ = id;
account()->pepManager()->publish(PEP_AVATAR_DATA_NS, PubSubItem(id, el));
}
setSelfAvatar(QImage(fileName));
} else {
account()->pepManager()->disable(PEP_AVATAR_METADATA_TN, PEP_AVATAR_METADATA_NS, {});
}
}

void AvatarFactory::setSelfAvatar(const QImage &image)
{
if (image.isNull()) {
account()->pepManager()->disable(PEP_AVATAR_METADATA_TN, PEP_AVATAR_METADATA_NS, {});
} else {
// Publish data

QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
auto maxSz = maxAvatarSize();
image.scaled(image.size().boundedTo(QSize(maxSz, maxSz)), Qt::KeepAspectRatio, Qt::SmoothTransformation)
.save(&buffer, "PNG", 0);
auto hash = QCryptographicHash::hash(data, QCryptographicHash::Sha1);
QString id = QString::fromLatin1(hash.toHex());

QDomDocument *doc = account()->client()->doc();
QDomElement el = doc->createElementNS(PEP_AVATAR_DATA_NS, PEP_AVATAR_DATA_TN);
el.appendChild(doc->createTextNode(QString::fromLatin1(data.toBase64())));
d->selfAvatarData_ = data;
d->selfAvatarHash_ = id;
account()->pepManager()->publish(PEP_AVATAR_DATA_NS, PubSubItem(id, el));
}
}

void AvatarFactory::importManualAvatar(const Jid &j, const QString &fileName)
{
AvatarCache::instance()->importManualAvatar(j, fileName);
Expand Down Expand Up @@ -1081,13 +1087,13 @@ void AvatarFactory::publish_success(const QString &n, const PubSubItem &item)
info_el.setAttribute("type", image2type(d->selfAvatarData_));
meta_el.appendChild(info_el);
account()->pepManager()->publish(PEP_AVATAR_METADATA_NS, PubSubItem(d->selfAvatarHash_, meta_el));
if (account()->client()->serverInfoManager()->account_features().hasAvatarConversion()) {
if (account()->client()->serverInfoManager()->accountFeatures().hasAvatarConversion()) {
VCardFactory::instance()->setPhoto(account()->jid(), d->selfAvatarData_, {});
}
d->selfAvatarData_.clear(); // we don't need it anymore
} else if (n == PEP_AVATAR_METADATA_NS) {
bool removed = item.payload().firstChildElement("metadata").firstChildElement("info").isNull();
if (account()->client()->serverInfoManager()->account_features().hasAvatarConversion() && removed) {
if (account()->client()->serverInfoManager()->accountFeatures().hasAvatarConversion() && removed) {
VCardFactory::instance()->deletePhoto(account()->jid(), {});
}
}
Expand Down
1 change: 1 addition & 0 deletions src/avatars.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class AvatarFactory : public QObject {
UserHashes userHashes(const Jid &jid) const;
PsiAccount *account() const;
void setSelfAvatar(const QString &fileName);
void setSelfAvatar(const QImage &image);

void importManualAvatar(const Jid &j, const QString &fileName);
void removeManualAvatar(const Jid &j);
Expand Down
31 changes: 27 additions & 4 deletions src/infodlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "infodlg.h"

#include "avatars.h"
#include "busywidget.h"
#include "common.h"
#include "desktoputil.h"
Expand All @@ -39,6 +40,7 @@
#include "userlist.h"
#include "vcardfactory.h"
#include "vcardphotodlg.h"
#include "xmpp/xmpp-im/xmpp_caps.h"
#include "xmpp/xmpp-im/xmpp_vcard4.h"

#include <QAction>
Expand Down Expand Up @@ -150,6 +152,7 @@ class InfoWidget::Private {
bool busy = false;
bool te_edited = false;
QByteArray photo;
QString photoMime;
QDate bday;
QString dateTextFormat;
QList<QString> infoRequested;
Expand Down Expand Up @@ -455,7 +458,26 @@ void InfoWidget::setData(const VCard4::VCard &i)
clearPhoto();
}
} else {
clearPhoto();
bool usePubsubAvatar
= (d->type == Contact && d->pa->client()->capsManager()->features(d->jid).hasAvatarConversion())
|| (d->type == Self && d->pa->client()->serverInfoManager()->accountFeatures().hasAvatarConversion());
if (usePubsubAvatar) {
// it has to be always updated in avatars cache
auto pix = d->pa->avatarFactory()->getAvatar(d->jid);
if (pix.isNull()) {
clearPhoto();
} else {
// yes we could use pixmap directly. let's keep it for future code optimization
QByteArray ba;
QBuffer b(&ba);
b.open(QIODevice::WriteOnly);
pix.toImage().save(&b, "PNG");
d->photo = ba;
updatePhoto();
}
} else {
clearPhoto();
}
}

setEdited(false);
Expand All @@ -475,8 +497,11 @@ bool InfoWidget::updatePhoto()
{
const QImage img = QImage::fromData(d->photo);
if (img.isNull()) {
d->photo = {};
return false;
}
QMimeDatabase db;
d->photoMime = db.mimeTypeForData(d->photo).name();
int max_width = m_ui.tb_photo->width() - 10; // FIXME: Ugly magic number
int max_height = m_ui.tb_photo->height() - 10; // FIXME: Ugly magic number

Expand Down Expand Up @@ -835,9 +860,7 @@ VCard4::VCard InfoWidget::makeVCard()

// Photo
if (!d->photo.isEmpty()) {
PAdvUris photos;
photos.append({ Parameters(), UriValue(d->photo) });
v.setPhoto(photos);
v.setPhoto(UriValue(d->photo, d->photoMime));
}

// Address
Expand Down
2 changes: 1 addition & 1 deletion src/psiaccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2387,7 +2387,7 @@ void PsiAccount::serverFeaturesChanged()
j->go(true);
}

if (d->client->serverInfoManager()->server_features().hasVCard() && !d->vcardChecked) {
if (d->client->serverInfoManager()->serverFeatures().hasVCard() && !d->vcardChecked) {
// Get the vcard
const auto vcard = VCardFactory::instance()->vcard(d->jid);
if (PsiOptions::instance()->getOption("options.vcard.query-own-vcard-on-login").toBool() || vcard.isEmpty()
Expand Down
21 changes: 20 additions & 1 deletion src/vcardfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "vcardfactory.h"

#include "applicationinfo.h"
#include "avatars.h"
#include "iris/xmpp_client.h"
#include "iris/xmpp_tasks.h"
#include "iris/xmpp_vcard.h"
Expand All @@ -40,6 +41,7 @@
#include <QMap>
#include <QObject>
#include <QTextStream>
#include <ranges>

// #define VCF_DEBUG 1

Expand Down Expand Up @@ -247,7 +249,24 @@ Task *VCardFactory::setVCard(PsiAccount *account, const VCard4::VCard &v, const
return jtVCard_;
}
QDomDocument *doc = account->client()->doc();
auto el = v.toXmlElement(*doc);
QDomElement el;
QByteArray avatarData = v.photo();
if (avatarData.isEmpty() || !account->serverInfoManager()->accountFeatures().hasAvatarConversion()) {
el = v.toXmlElement(*doc);
} else {
// let's better publish avatar via avatar service
QImage image = QImage::fromData(avatarData);
account->avatarFactory()->setSelfAvatar(image);
VCard4::VCard v2 = v;
v2.detach();
VCard4::PAdvUris photos;
for (auto const &uri :
v2.photo() | std::views::filter([](auto const &item) { return item.data.data.isEmpty(); })) {
photos.append(uri);
}
v2.setPhoto(photos);
el = v2.toXmlElement(*doc);
}
return account->pepManager()->publish(QLatin1String(PEP_VCARD4_NODE), PubSubItem(QLatin1String("current"), el));
}

Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.5.1963 (2024-06-12, 235bc8f6)
1.5.1964 (2024-06-12, d2e744ac)

0 comments on commit a87ae2f

Please sign in to comment.