From 03d6596b8d6b45d83658f04a9a809d80cf901c2e Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Wed, 13 Nov 2019 12:59:52 -0500 Subject: [PATCH] messaging: save/restore draft messages Change-Id: I6609cccdcc5e6ab4c86cad112d4a7c22900d2bfb --- callwidget.cpp | 32 ++++++++++++++++++++++---------- conversationitemdelegate.cpp | 26 ++++++++++++++++++++++++++ lrcinstance.h | 17 +++++++++++++++++ messagewebview.cpp | 33 +++++++++++++++++++++++++++++++-- messagewebview.h | 4 ++++ smartlistmodel.cpp | 2 ++ smartlistmodel.h | 3 ++- 7 files changed, 104 insertions(+), 13 deletions(-) diff --git a/callwidget.cpp b/callwidget.cpp index ddb01db..2676918 100644 --- a/callwidget.cpp +++ b/callwidget.cpp @@ -976,18 +976,30 @@ CallWidget::setupChatView(const lrc::api::conversation::Info& convInfo) ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn); ui->messageView->setMessagesVisibility(false); - Utils::oneShotConnect(ui->messageView, &MessageWebView::messagesCleared, - [this, convInfo] { - auto convModel = LRCInstance::getCurrentConversationModel(); - ui->messageView->printHistory(*convModel, convInfo.interactions); - Utils::oneShotConnect(ui->messageView, &MessageWebView::messagesLoaded, - [this] { - ui->messageView->setMessagesVisibility(true); + Utils::oneShotConnect(ui->messageView, &MessageWebView::sendMessageContentSaved, + [this, &convInfo, &accountInfo, lastConvUid = lastConvUid_](const QString& content) { + if (!lastConvUid.empty()) { + LRCInstance::setContentDraft( + lastConvUid.c_str(), accountInfo.id.c_str(), content); + } + Utils::oneShotConnect(ui->messageView, &MessageWebView::messagesCleared, + [this, &convInfo] { + auto convModel = LRCInstance::getCurrentConversationModel(); + ui->messageView->printHistory(*convModel, convInfo.interactions); + Utils::oneShotConnect(ui->messageView, &MessageWebView::messagesLoaded, + [this] { + ui->messageView->setMessagesVisibility(true); + }); + setConversationProfileData(convInfo); }); - setConversationProfileData(convInfo); + ui->messageView->setInvitation(false); + ui->messageView->clear(); + auto restoredContent = LRCInstance::getContentDraft( + convInfo.uid.c_str(), accountInfo.id.c_str()); + ui->messageView->setSendMessageContent(restoredContent); + ui->smartList->update(); }); - ui->messageView->setInvitation(false); - ui->messageView->clear(); + ui->messageView->requestSendMessageContent(); } void diff --git a/conversationitemdelegate.cpp b/conversationitemdelegate.cpp index 3733a76..eba9000 100644 --- a/conversationitemdelegate.cpp +++ b/conversationitemdelegate.cpp @@ -272,6 +272,32 @@ ConversationItemDelegate::paintConversationItem(QPainter* painter, } // bottom-right: last interaction snippet or call state (if in call) + auto draft = index.data(static_cast<int>(SmartListModel::Role::Draft)).value<QString>(); + if (!draft.isEmpty()) { + painter->save(); + uint cp = 0x270F; + auto emojiString = QString::fromUcs4(&cp, 1); + QFont emojiMsgFont(QStringLiteral("Segoe UI Emoji")); + emojiMsgFont.setPointSize(scalingRatio > 1.0 ? fontSize_ - 2 : fontSize_); + + QString text{ tr("Draft") }; + int widthText{ QFontMetrics(font).width(text) }; + int widthEmoji{ QFontMetrics(emojiMsgFont).width(emojiString) }; + int margin { 4 }; + + painter->setFont(font); + painter->setPen(QColor(207, 83, 0)); + painter->drawText(rectInfo2, Qt::AlignVCenter | Qt::AlignRight, text); + + rectInfo2.moveTop(rectInfo2.top() - 2); + painter->setOpacity(0.7); + painter->setFont(emojiMsgFont); + painter->drawText(rectInfo2.right() - widthText - widthEmoji - margin, rectInfo2.y(), + widthEmoji, rectInfo2.height(), Qt::AlignVCenter, emojiString); + painter->restore(); + return; + } + if (index.data(static_cast<int>(SmartListModel::Role::InCall)).value<bool>()) { QString callStateStr = index.data(static_cast<int>(SmartListModel::Role::CallStateStr)).value<QString>(); if (!callStateStr.isNull()) { diff --git a/lrcinstance.h b/lrcinstance.h index 82d14c6..056f0f4 100644 --- a/lrcinstance.h +++ b/lrcinstance.h @@ -338,6 +338,22 @@ public: f(); } } + + static QString getContentDraft(const QString& convUid, + const QString& accountId) + { + auto draftKey = accountId + "_" + convUid; + return instance().contentDrafts_[draftKey]; + } + + static void setContentDraft(const QString& convUid, + const QString& accountId, + const QString& content) + { + auto draftKey = accountId + "_" + convUid; + instance().contentDrafts_[draftKey] = content; + } + signals: void accountListChanged(); @@ -355,4 +371,5 @@ private: AccountListModel accountListModel_; std::string selectedAccountId_; std::string selectedConvUid_; + MapStringString contentDrafts_; }; diff --git a/messagewebview.cpp b/messagewebview.cpp index 0553c84..e22923b 100644 --- a/messagewebview.cpp +++ b/messagewebview.cpp @@ -457,6 +457,21 @@ MessageWebView::displayNavbar(bool display) page()->runJavaScript(s, QWebEngineScript::MainWorld); } +void +MessageWebView::requestSendMessageContent() +{ + QString s = QString::fromLatin1("requestSendMessageContent();"); + page()->runJavaScript(s, QWebEngineScript::MainWorld); +} + +void +MessageWebView::setSendMessageContent(const QString& content) +{ + QString s = QString::fromLatin1("setSendMessageContent(`%1`);") + .arg(content); + page()->runJavaScript(s, QWebEngineScript::MainWorld); +} + // JS bridging incoming Q_INVOKABLE int PrivateBridging::log(const QString& arg) @@ -715,7 +730,7 @@ PrivateBridging::emitPasteKeyDetected() return 0; } -int +Q_INVOKABLE int PrivateBridging::openAudioRecorder(int spikePosX, int spikePosY) { //call the open audio recorder function in messageweview @@ -729,7 +744,7 @@ PrivateBridging::openAudioRecorder(int spikePosX, int spikePosY) return 0; } -int +Q_INVOKABLE int PrivateBridging::openVideoRecorder(int spikePosX, int spikePosY) { //call the open video recorder function in messageweview @@ -741,4 +756,18 @@ PrivateBridging::openVideoRecorder(int spikePosX, int spikePosY) qDebug() << "JS bridging - exception during openVideoRecorder!"; } return 0; +} + +Q_INVOKABLE int +PrivateBridging::saveSendMessageContent(const QString& arg) +{ + try { + if (auto messageView = qobject_cast<MessageWebView*>(this->parent())) { + emit messageView->sendMessageContentSaved(arg); + } + } catch (...) { + qDebug() << "JS bridging - exception during saveSendMessageContent!"; + } + return 0; + } \ No newline at end of file diff --git a/messagewebview.h b/messagewebview.h index d782aff..3573ec4 100644 --- a/messagewebview.h +++ b/messagewebview.h @@ -53,6 +53,7 @@ public: Q_INVOKABLE int emitPasteKeyDetected(); Q_INVOKABLE int openAudioRecorder(int spikePosX,int spikePosY); Q_INVOKABLE int openVideoRecorder(int spikePosX,int spikePosY); + Q_INVOKABLE int saveSendMessageContent(const QString& arg); }; class MessageWebView : public QWebEngineView @@ -97,6 +98,8 @@ public: void updateChatviewFrame(bool accountEnabled, bool isBanned, bool isTemporary, const QString& alias, const QString& bestId); void displayNavbar(bool display); + void requestSendMessageContent(); + void setSendMessageContent(const QString& content); protected: @@ -114,6 +117,7 @@ signals: void textSelectedReady(); void pasteKeyDetected(); void invitationAccepted(); + void sendMessageContentSaved(const QString& content); private slots: void slotLoadFinished(); diff --git a/smartlistmodel.cpp b/smartlistmodel.cpp index 234917d..0c326d0 100644 --- a/smartlistmodel.cpp +++ b/smartlistmodel.cpp @@ -239,6 +239,8 @@ SmartListModel::getConversationItemData(const conversation::Info& item, } case Role::SectionName: return QVariant(QString()); + case Role::Draft: + return LRCInstance::getContentDraft(item.uid.c_str(), accountInfo.id.c_str()); } return QVariant(); } diff --git a/smartlistmodel.h b/smartlistmodel.h index 76657ac..108e08b 100644 --- a/smartlistmodel.h +++ b/smartlistmodel.h @@ -58,7 +58,8 @@ public: InCall, CallStateStr, SectionName, - AccountId + AccountId, + Draft }; explicit SmartListModel(const std::string& accId, -- GitLab