Browse Source

Display group avatars and restrict editing to group key holders

master
evgeny 7 days ago
parent
commit
4062ecdfb1
  1. 1
      tools/chatgui/CMakeLists.txt
  2. 20
      tools/chatgui/src/channellist.cpp
  3. 32
      tools/chatgui/src/channelsettingsdialog.cpp

1
tools/chatgui/CMakeLists.txt

@ -180,6 +180,7 @@ add_executable(vibechat
src/member_files/browser.cpp
src/avatars/avatarcache.cpp
src/avatars/avatarmanager.cpp
src/avatars/groupavatarmanager.cpp
src/audiodevicesettingspage.cpp
src/storagesettingspage.cpp
src/connmonitorwindow.cpp

20
tools/chatgui/src/channellist.cpp

@ -1,12 +1,14 @@
#include <QCoreApplication>
#include "channellist.h"
#include "channeldelegate.h"
#include "avatars/groupavatarmanager.h"
#include "../db/db_manager.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QPainter>
#include <QPainterPath>
#include <QPixmap>
#include <QMouseEvent>
#include <QMenu>
@ -130,6 +132,15 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent)
, m_model(new QStandardItemModel(this))
, m_db(db)
{
if (auto* avatars = GroupAvatarManager::instance()) connect(avatars, &GroupAvatarManager::changed, this,
[this, avatars](const QString& channel) {
const QImage image = avatars->currentImage(channel); if (image.isNull()) return;
QPixmap pixmap(64, 64); pixmap.fill(Qt::transparent); QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing); QPainterPath path; path.addEllipse(QRectF(0, 0, 64, 64));
painter.setClipPath(path); painter.drawImage(QRect(0, 0, 64, 64), image); painter.end();
for (int row = 0; row < m_model->rowCount(); row++) if (m_model->item(row)->data(ChannelChannelIdRole).toString() == channel)
m_model->item(row)->setData(QIcon(pixmap), ChannelIconRole);
});
m_dmPresenceTimer = new QTimer(this);
m_dmPresenceTimer->setSingleShot(true);
m_dmPresenceTimer->setInterval(50);
@ -294,6 +305,15 @@ void ChannelList::loadChannels() {
item->setData(ch.unreadCount, ChannelUnreadCountRole);
item->setData(ch.lastMsgAt, ChannelLastMsgAtRole);
item->setData(makeChannelIcon(colors[ci % 6], letter), ChannelIconRole);
if (auto* avatars = GroupAvatarManager::instance()) {
const QImage image = avatars->image(ch.channelId, ch.avatarVersion, ch.avatarHash);
if (!image.isNull()) {
QPixmap pixmap(64, 64); pixmap.fill(Qt::transparent); QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing); QPainterPath clip; clip.addEllipse(QRectF(0, 0, 64, 64));
painter.setClipPath(clip); painter.drawImage(QRect(0, 0, 64, 64), image); painter.end();
item->setData(QIcon(pixmap), ChannelIconRole);
}
}
m_model->appendRow(item);
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT, "ChannelList::loadChannels row=%d cid='%s' name='%s' unread=%d lastMsgAt=%lld",
m_model->rowCount()-1, qPrintable(ch.channelId), qPrintable(ch.name), ch.unreadCount,

32
tools/chatgui/src/channelsettingsdialog.cpp

@ -1,5 +1,6 @@
#include <QCoreApplication>
#include "channelsettingsdialog.h"
#include "avatars/groupavatarmanager.h"
#include "../db/db_manager.h"
#include "../transport/gui_bridge.h"
#include "../../lib/mem.h"
@ -10,6 +11,7 @@ extern "C" {
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QFileDialog>
#include <cstring>
ChannelSettingsDialog::ChannelSettingsDialog(const QString& channelId, DbManager* db, QWidget* parent)
@ -34,6 +36,36 @@ ChannelSettingsDialog::ChannelSettingsDialog(const QString& channelId, DbManager
chIdLabel->setWordWrap(true);
layout->addWidget(chIdLabel);
if (auto* avatars = GroupAvatarManager::instance()) {
auto* preview = new QLabel(this); preview->setFixedSize(64, 64); layout->addWidget(preview);
auto* buttons = new QHBoxLayout;
auto* upload = new QPushButton(QCoreApplication::translate("ChatGui", "Upload group avatar"), this);
auto* remove = new QPushButton(QCoreApplication::translate("ChatGui", "Remove group avatar"), this);
upload->setObjectName("uploadGroupAvatar"); remove->setObjectName("removeGroupAvatar");
bool hasKey = false;
if (db && db->isOpen()) for (const auto& row : db->getChannels())
if (row.channelId == channelId) hasKey = row.ed25519_privkey.size() == 32;
upload->setEnabled(hasKey); remove->setEnabled(hasKey);
auto* info = new QLabel(QCoreApplication::translate("ChatGui", "Group avatar: up to 16 KiB. Changes apply immediately and require the group key."), this);
info->setWordWrap(true); auto* result = new QLabel(this); result->setWordWrap(true);
buttons->addWidget(upload); buttons->addWidget(remove); layout->addLayout(buttons); layout->addWidget(info); layout->addWidget(result);
auto refresh = [avatars, preview, channelId] {
const QImage image = avatars->image(channelId);
if (image.isNull()) { preview->setPixmap(QPixmap()); preview->setText(QCoreApplication::translate("ChatGui", "No avatar")); }
else preview->setPixmap(QPixmap::fromImage(image).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
};
connect(avatars, &GroupAvatarManager::changed, this, [channelId, refresh](const QString& channel) { if (channel == channelId) refresh(); });
connect(avatars, &GroupAvatarManager::status, this, [channelId, result, refresh](const QString& channel, const QString& message) {
if (channel == channelId) { result->setText(message); refresh(); }
});
connect(upload, &QPushButton::clicked, this, [this, avatars, channelId] {
const QString file = QFileDialog::getOpenFileName(this, QCoreApplication::translate("ChatGui", "Choose avatar"), {},
QCoreApplication::translate("ChatGui", "Images (*.png *.jpg *.jpeg *.webp)"));
if (!file.isEmpty()) avatars->upload(channelId, file);
});
connect(remove, &QPushButton::clicked, this, [avatars, channelId] { avatars->remove(channelId); }); refresh();
}
layout->addSpacing(8);
m_autoPlayVoice = new QCheckBox(QCoreApplication::translate("ChatGui", "Auto-play voice messages on receive"), this);

Loading…
Cancel
Save