diff --git a/tools/chatgui/src/messagedelegate.cpp b/tools/chatgui/src/messagedelegate.cpp index ed2955a3..26a0eb9c 100644 --- a/tools/chatgui/src/messagedelegate.cpp +++ b/tools/chatgui/src/messagedelegate.cpp @@ -1573,6 +1573,7 @@ void MessageDelegate::drawStatusBar(QPainter *p, const Layout &L, } QFont countFont = opt.font; + countFont.setBold(rm.value("mine").toBool()); countFont.setPointSize(countFont.pointSize() - 2); p->setFont(countFont); p->setPen(QColor(0x80, 0x80, 0x80)); diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index 6cebe3e2..d6dcc9ac 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -1054,21 +1054,40 @@ void MessageList::onMessageContextMenu(const QPoint& pos) { bool isImage = ct.startsWith("image/"); bool isDmFile = isDmChannel(idx.data(MsgChannelIdRole).toString()) && ct == "application/octet-stream"; bool isDm = isDmChannel(idx.data(MsgChannelIdRole).toString()); - if (!isVideo && !isImage && !isDmFile) return; QString filePath = idx.data(MsgVoiceFileRole).toString(); QString displayName = idx.data(MsgFileDisplayNameRole).toString(); bool downloaded = !filePath.isEmpty() && QFile::exists(filePath); QMenu menu(m_view); - QAction* saveAct = menu.addAction(QCoreApplication::translate("ChatGui", "Save to file")); - saveAct->setEnabled(downloaded); + QString messageId = idx.data(MsgMessageKeyRole).toString(); + if (!isDm && messageId.size() == 64) { + if (ct == "poll") connect(menu.addAction(QCoreApplication::translate("ChatGui", "Vote / results")), &QAction::triggered, + this, [this, messageId]() { showPoll(messageId); }); + auto* reactions = menu.addMenu(QCoreApplication::translate("ChatGui", "React")); + QSet 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 = reactions->addAction(QString::fromUtf8(chat_reaction_emoji(i))); + action->setCheckable(true); action->setChecked(mine.contains(i)); + connect(action, &QAction::triggered, this, [this, messageId, i]() { + sendFeedback({{"cmd", "react"}, {"message_id", messageId}, {"emoji", (int)i}}); + }); + } + connect(menu.addAction(QCoreApplication::translate("ChatGui", "Clear reactions")), &QAction::triggered, + this, [this, messageId]() { sendFeedback({{"cmd", "react"}, {"message_id", messageId}, {"clear", true}}); }); + } + QAction* saveAct = nullptr; + if (isVideo || isImage || isDmFile) { + saveAct = menu.addAction(QCoreApplication::translate("ChatGui", "Save to file")); saveAct->setEnabled(downloaded); + } QAction* dlAct = nullptr; - if (!downloaded && !isDm) dlAct = menu.addAction(QCoreApplication::translate("ChatGui", "Download")); + if ((isVideo || isImage) && !downloaded && !isDm) dlAct = menu.addAction(QCoreApplication::translate("ChatGui", "Download")); QAction* chosen = menu.exec(m_view->viewport()->mapToGlobal(pos)); - if (chosen == saveAct) { + if (saveAct && chosen == saveAct) { QString base = displayName; if (base.isEmpty()) base = QFileInfo(filePath).fileName(); QString dest = QFileDialog::getSaveFileName(this, QCoreApplication::translate("ChatGui", "Save file"), base);