|
|
|
|
@ -18,6 +18,8 @@
|
|
|
|
|
#include <QMessageBox> |
|
|
|
|
#include <QJsonDocument> |
|
|
|
|
#include <QJsonArray> |
|
|
|
|
#include <QMenu> |
|
|
|
|
#include <QCursor> |
|
|
|
|
#include <cstring> |
|
|
|
|
|
|
|
|
|
extern "C" { |
|
|
|
|
@ -26,6 +28,34 @@ extern "C" {
|
|
|
|
|
|
|
|
|
|
static QString feedbackText(const char* source) { return QCoreApplication::translate("ChatGui", source); } |
|
|
|
|
|
|
|
|
|
void MessageList::addReactionActions(QMenu* menu, const QString& channel, const QString& messageId) { |
|
|
|
|
QSet<int> mine; |
|
|
|
|
for (const auto& value : m_feedback.value(messageId).value("reactions").toArray()) |
|
|
|
|
if (value.toObject().value("mine").toBool()) mine.insert(value.toObject().value("id").toInt()); |
|
|
|
|
for (unsigned i = 0; i < CHAT_REACTION_COUNT; i++) { |
|
|
|
|
auto* action = menu->addAction(QString::fromUtf8(chat_reaction_emoji(i))); |
|
|
|
|
action->setCheckable(true); action->setChecked(mine.contains(i)); |
|
|
|
|
connect(action, &QAction::triggered, this, [this, channel, messageId, i]() { |
|
|
|
|
GUI_DEBUG("reaction: chosen ch=%s message=%s emoji=%u", qPrintable(channel), qPrintable(messageId), i); |
|
|
|
|
sendFeedback({{"cmd", "react"}, {"ch", channel}, {"message_id", messageId}, {"emoji", (int)i}}); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageList::requestReaction(const QModelIndex& index, int emoji) { |
|
|
|
|
const QString channel = index.data(MsgChannelIdRole).toString(), messageId = index.data(MsgMessageKeyRole).toString(); |
|
|
|
|
if (!index.isValid() || channel.isEmpty() || isDmChannel(channel) || messageId.size() != 64 |
|
|
|
|
|| emoji < -1 || emoji >= CHAT_REACTION_COUNT) { |
|
|
|
|
GUI_WARN("reaction: invalid target ch=%s key_bytes=%d emoji=%d", qPrintable(channel), messageId.size(), emoji); return; |
|
|
|
|
} |
|
|
|
|
if (emoji >= 0) { |
|
|
|
|
GUI_DEBUG("reaction: toggled ch=%s message=%s emoji=%d", qPrintable(channel), qPrintable(messageId), emoji); |
|
|
|
|
sendFeedback({{"cmd", "react"}, {"ch", channel}, {"message_id", messageId}, {"emoji", emoji}}); return; |
|
|
|
|
} |
|
|
|
|
GUI_DEBUG("reaction: picker opened ch=%s message=%s", qPrintable(channel), qPrintable(messageId)); |
|
|
|
|
QMenu menu(m_view); addReactionActions(&menu, channel, messageId); menu.exec(QCursor::pos()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Итог для баббла и открытого диалога; строковые поля показываем как обычный текст. */ |
|
|
|
|
static QString pollSummary(const QJsonObject& poll) { |
|
|
|
|
QString text = poll.value("question").toString(); |
|
|
|
|
|