Browse Source

Display cached user avatars in member lists and chat messages

master
evgeny 6 days ago
parent
commit
694ed8e263
  1. 2
      tools/chatgui/CMakeLists.txt
  2. 23
      tools/chatgui/src/memberlistmodel.cpp
  3. 25
      tools/chatgui/src/messagelist.cpp

2
tools/chatgui/CMakeLists.txt

@ -178,6 +178,8 @@ add_executable(vibechat
src/videoplayer_window.cpp
src/imageviewer_window.cpp
src/member_files/browser.cpp
src/avatars/avatarcache.cpp
src/avatars/avatarmanager.cpp
src/audiodevicesettingspage.cpp
src/storagesettingspage.cpp
src/connmonitorwindow.cpp

23
tools/chatgui/src/memberlistmodel.cpp

@ -1,5 +1,6 @@
#include <QCoreApplication>
#include "memberlistmodel.h"
#include "avatars/avatarmanager.h"
#include "../transport/gui_bridge.h"
#include <QPainter>
#include <QFont>
@ -12,12 +13,28 @@ extern "C" {
#include "../../../lib/mem.h"
}
#define CHAT_MEMBER_DISPLAY_SIZE 79
static void applyPhoto(MemberListItem& item, const QString& channel) {
auto* manager = AvatarManager::instance(); if (!manager) return;
const QImage image = manager->image(channel, item.nodeId); if (image.isNull()) return;
QPixmap pixmap(24, 24); pixmap.fill(Qt::transparent);
QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing);
QPainterPath clip; clip.addEllipse(QRectF(0, 0, 24, 24)); painter.setClipPath(clip);
painter.drawImage(QRect(0, 0, 24, 24), image); painter.setClipping(false);
painter.setPen(QPen(Qt::white, 1)); painter.setBrush(item.online ? QColor("#4CAF50") : QColor("#9E9E9E"));
painter.drawEllipse(QRect(17, 17, 6, 6)); painter.end(); item.avatar = pixmap;
}
MemberListModel::MemberListModel(QObject* parent)
: QAbstractListModel(parent)
, m_rttTimer(new QTimer(this))
{
if (auto* manager = AvatarManager::instance()) connect(manager, &AvatarManager::changed, this,
[this](const QString& channel, quint64 owner) {
if (channel != m_channelId) return;
for (auto it = m_cache.begin(); it != m_cache.end(); ++it) if (it->nodeId == owner) {
applyPhoto(*it, channel); emit dataChanged(index(it.key()), index(it.key()), {Qt::DecorationRole});
}
});
m_rttTimer->setInterval(2000);
connect(m_rttTimer, &QTimer::timeout, this, &MemberListModel::refreshRtt);
m_rttTimer->start();
@ -133,8 +150,8 @@ static void deserialize_member(const uint8_t* src, MemberListItem& item) {
}
void MemberListModel::onMemberList(const QString& chId, int count, const uint8_t* data, int dataLen) {
(void)dataLen;
if (chId != m_channelId) return;
if (count < 0 || count > dataLen / CHAT_MEMBER_DISPLAY_SIZE) return;
beginResetModel();
m_totalCount = 0;
@ -144,6 +161,7 @@ void MemberListModel::onMemberList(const QString& chId, int count, const uint8_t
for (int i = 0; i < count; i++) {
MemberListItem item;
deserialize_member(data + i * CHAT_MEMBER_DISPLAY_SIZE, item);
applyPhoto(item, chId);
if ((item.flags & CHAT_MEMBER_FLAG_DELETED) && !m_isOwner) continue;
m_cache[row++] = item;
}
@ -156,6 +174,7 @@ void MemberListModel::onMemberUpdated(const QString& chId, const uint8_t* data)
MemberListItem item;
deserialize_member(data, item);
applyPhoto(item, chId);
/* find existing row by nodeId */
int row = -1;

25
tools/chatgui/src/messagelist.cpp

@ -54,6 +54,7 @@ void chat_core_save_ui_state_trampoline(void* arg);
#include "radio_audio_engine.h"
#include "radiopanel.h"
#include "flagpainter.h"
#include "avatars/avatarmanager.h"
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
@ -336,6 +337,22 @@ MessageList::MessageList(DbManager* db, AudioRecorder* recorder, QWidget *parent
, m_recorder(recorder)
{
auto *layout = new QVBoxLayout(this);
if (auto* manager = AvatarManager::instance()) connect(manager, &AvatarManager::changed, this,
[this, manager](const QString& channel, quint64 owner) {
if (channel != m_currentChannelId) return;
const QImage image = manager->image(channel, owner);
for (int row = 0; row < m_model->rowCount(); row++) {
auto* item = m_model->item(row);
if (item->data(MsgAuthorNodeIdRole).toULongLong() != owner) continue;
QPixmap avatar;
if (!image.isNull()) avatar = QPixmap::fromImage(image);
else {
const AccountRow account = m_db->getAccount(owner);
avatar = makeAvatar(QColor(account.avatarColor), account.avatarLetter.isEmpty() ? authorName(owner).left(1) : account.avatarLetter);
}
item->setData(avatar, MsgAvatarRole);
}
});
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
@ -701,6 +718,10 @@ void MessageList::loadChannel(const QString& channelId) {
}
auto avatar = makeAvatar(color, letter);
if (auto* manager = AvatarManager::instance()) {
const QImage image = manager->image(m_currentChannelId, m.authorNodeId);
if (!image.isNull()) avatar = QPixmap::fromImage(image);
}
auto time = QDateTime::fromMSecsSinceEpoch(m.timestamp).toString("HH:mm");
QVariantList reacts;
@ -775,6 +796,10 @@ void MessageList::refresh() {
if (!m_avatarCache.contains(m.authorNodeId))
m_avatarCache[m.authorNodeId] = color;
auto avatar = makeAvatar(color, letter);
if (auto* manager = AvatarManager::instance()) {
const QImage image = manager->image(m_currentChannelId, m.authorNodeId);
if (!image.isNull()) avatar = QPixmap::fromImage(image);
}
auto time = QDateTime::fromMSecsSinceEpoch(m.timestamp).toString("HH:mm");
auto *item = new QStandardItem();
setMsg(item, author, QString::fromUtf8(m.data), time, avatar, false,

Loading…
Cancel
Save