From 617855a780a8516bca5c4c2eacced214e7e9ecbf Mon Sep 17 00:00:00 2001 From: Black Hat Date: Sun, 29 Sep 2019 20:29:59 -0700 Subject: [PATCH] Fix line strike. Fix code block wrapping. Fix replyModel being garbage collected. Reply message in RoomPanelInput is richtext now. --- imports/Spectral/Component/AutoRectangle.qml | 80 +++++++++++++++++++ .../Component/Timeline/FileDelegate.qml | 2 +- .../Component/Timeline/ImageDelegate.qml | 2 +- .../Component/Timeline/MessageDelegate.qml | 4 +- .../Component/Timeline/VideoDelegate.qml | 2 +- imports/Spectral/Panel/RoomPanelInput.qml | 15 +++- src/messageeventmodel.cpp | 8 +- src/spectralroom.cpp | 37 ++++++--- src/spectralroom.h | 2 +- src/utils.cpp | 14 ---- src/utils.h | 7 +- 11 files changed, 131 insertions(+), 42 deletions(-) diff --git a/imports/Spectral/Component/AutoRectangle.qml b/imports/Spectral/Component/AutoRectangle.qml index 975e491b3..8167a991c 100644 --- a/imports/Spectral/Component/AutoRectangle.qml +++ b/imports/Spectral/Component/AutoRectangle.qml @@ -25,6 +25,26 @@ Rectangle { antialiasing: true color: parent.color + + Rectangle { + anchors.bottom: parent.bottom + anchors.left: parent.left + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } + + Rectangle { + anchors.top: parent.top + anchors.right: parent.right + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } } Rectangle { @@ -39,6 +59,26 @@ Rectangle { antialiasing: true color: parent.color + + Rectangle { + anchors.bottom: parent.bottom + anchors.right: parent.right + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } + + Rectangle { + anchors.top: parent.top + anchors.left: parent.left + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } } Rectangle { @@ -53,6 +93,26 @@ Rectangle { antialiasing: true color: parent.color + + Rectangle { + anchors.bottom: parent.bottom + anchors.right: parent.right + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } + + Rectangle { + anchors.top: parent.top + anchors.left: parent.left + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } } Rectangle { @@ -67,5 +127,25 @@ Rectangle { antialiasing: true color: parent.color + + Rectangle { + anchors.bottom: parent.bottom + anchors.left: parent.left + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } + + Rectangle { + anchors.top: parent.top + anchors.right: parent.right + + width: parent.width / 2 + height: parent.height / 2 + + color: parent.color + } } } diff --git a/imports/Spectral/Component/Timeline/FileDelegate.qml b/imports/Spectral/Component/Timeline/FileDelegate.qml index c5d9bdd74..99af026cf 100644 --- a/imports/Spectral/Component/Timeline/FileDelegate.qml +++ b/imports/Spectral/Component/Timeline/FileDelegate.qml @@ -164,7 +164,7 @@ RowLayout { contextMenu.downloadAndOpen.connect(downloadAndOpen) contextMenu.saveFileAs.connect(saveFileAs) contextMenu.reply.connect(function() { - roomPanelInput.replyModel = model + roomPanelInput.replyModel = Object.assign({}, model) roomPanelInput.isReply = true roomPanelInput.focus() }) diff --git a/imports/Spectral/Component/Timeline/ImageDelegate.qml b/imports/Spectral/Component/Timeline/ImageDelegate.qml index 132d737e3..6954081dd 100644 --- a/imports/Spectral/Component/Timeline/ImageDelegate.qml +++ b/imports/Spectral/Component/Timeline/ImageDelegate.qml @@ -158,7 +158,7 @@ RowLayout { contextMenu.downloadAndOpen.connect(downloadAndOpen) contextMenu.saveFileAs.connect(saveFileAs) contextMenu.reply.connect(function() { - roomPanelInput.replyModel = model + roomPanelInput.replyModel = Object.assign({}, model) roomPanelInput.isReply = true roomPanelInput.focus() }) diff --git a/imports/Spectral/Component/Timeline/MessageDelegate.qml b/imports/Spectral/Component/Timeline/MessageDelegate.qml index e921514e6..76acac3f8 100644 --- a/imports/Spectral/Component/Timeline/MessageDelegate.qml +++ b/imports/Spectral/Component/Timeline/MessageDelegate.qml @@ -72,7 +72,7 @@ ColumnLayout { padding: 0 background: AutoRectangle { - readonly property int minorRadius: 2 + readonly property int minorRadius: 8 id: bubbleBackground @@ -100,7 +100,7 @@ ColumnLayout { messageSourceDialog.createObject(ApplicationWindow.overlay, {"sourceText": toolTip}).open() }) contextMenu.reply.connect(function() { - roomPanelInput.replyModel = model + roomPanelInput.replyModel = Object.assign({}, model) roomPanelInput.isReply = true roomPanelInput.focus() }) diff --git a/imports/Spectral/Component/Timeline/VideoDelegate.qml b/imports/Spectral/Component/Timeline/VideoDelegate.qml index b6c764243..4e02475ff 100644 --- a/imports/Spectral/Component/Timeline/VideoDelegate.qml +++ b/imports/Spectral/Component/Timeline/VideoDelegate.qml @@ -173,7 +173,7 @@ RowLayout { contextMenu.downloadAndOpen.connect(downloadAndOpen) contextMenu.saveFileAs.connect(saveFileAs) contextMenu.reply.connect(function() { - roomPanelInput.replyModel = model + roomPanelInput.replyModel = Object.assign({}, model) roomPanelInput.isReply = true roomPanelInput.focus() }) diff --git a/imports/Spectral/Panel/RoomPanelInput.qml b/imports/Spectral/Panel/RoomPanelInput.qml index 50086eab9..2d44b99b9 100644 --- a/imports/Spectral/Panel/RoomPanelInput.qml +++ b/imports/Spectral/Panel/RoomPanelInput.qml @@ -16,7 +16,7 @@ Control { property var replyModel readonly property var replyUser: replyModel ? replyModel.author : null readonly property string replyEventID: replyModel ? replyModel.eventId : "" - readonly property string replyContent: replyModel ? replyModel.message : "" + readonly property string replyContent: replyModel ? replyModel.display : "" property alias isAutoCompleting: autoCompleteListView.visible property var autoCompleteModel @@ -62,13 +62,20 @@ Control { hint: replyUser ? replyUser.displayName : "No name" } - Label { + TextEdit { Layout.fillWidth: true - text: replyContent - font.pixelSize: 14 + color: MPalette.foreground + text: "" + replyContent + font.family: window.font.family + font.pixelSize: 14 + selectByMouse: true + readOnly: true wrapMode: Label.Wrap + selectedTextColor: "white" + selectionColor: MPalette.accent + textFormat: Text.RichText } } diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index 9481fb58f..df47f9a2b 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -285,12 +285,11 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { const auto& evt = isPending ? **pendingIt : **timelineIt; if (role == Qt::DisplayRole) { - return utils::cleanHTML( - utils::removeReply(m_currentRoom->eventToString(evt, Qt::RichText))); + return m_currentRoom->eventToString(evt, Qt::RichText); } if (role == MessageRole) { - return utils::removeReply(m_currentRoom->eventToString(evt)); + return m_currentRoom->eventToString(evt); } if (role == Qt::ToolTipRole) { @@ -443,8 +442,7 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { return QVariantMap{ {"eventId", replyEventId}, - {"display", utils::cleanHTML(utils::removeReply( - m_currentRoom->eventToString(replyEvt, Qt::RichText)))}, + {"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)}, {"author", QVariant::fromValue(m_currentRoom->user(replyEvt.senderId()))}}; } diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp index b51186cf6..14838de2e 100644 --- a/src/spectralroom.cpp +++ b/src/spectralroom.cpp @@ -118,7 +118,7 @@ QString SpectralRoom::lastEvent() const { return user(evt->senderId())->displayname() + (evt->isStateEvent() ? " " : ": ") + - utils::removeReply(eventToString(*evt)); + eventToString(*evt); } return ""; } @@ -230,18 +230,27 @@ QString SpectralRoom::avatarMediaId() const { } QString SpectralRoom::eventToString(const RoomEvent& evt, - Qt::TextFormat format) const { + Qt::TextFormat format, bool removeReply) const { const bool prettyPrint = (format == Qt::RichText); using namespace QMatrixClient; return visit( evt, - [prettyPrint](const RoomMessageEvent& e) { + [prettyPrint, removeReply](const RoomMessageEvent& e) { using namespace MessageEventContent; if (prettyPrint && e.hasTextContent() && - e.mimeType().name() != "text/plain") - return static_cast(e.content())->body; + e.mimeType().name() != "text/plain") { + auto htmlBody = static_cast(e.content())->body; + if (removeReply) { + htmlBody.remove(utils::removeRichReplyRegex); + } + htmlBody.replace(utils::userPillRegExp, "\\1"); + htmlBody.replace(utils::strikethroughRegExp, "\\1"); + htmlBody.push_front(""); + return htmlBody; + } + if (e.hasFileContent()) { auto fileCaption = e.content()->fileInfo()->originalName.toHtmlEscaped(); @@ -252,8 +261,18 @@ QString SpectralRoom::eventToString(const RoomEvent& evt, } return !fileCaption.isEmpty() ? fileCaption : tr("a file"); } - return prettyPrint ? QMatrixClient::prettyPrint(e.plainBody()) - : e.plainBody(); + + if (prettyPrint) { + auto plainBody = e.plainBody(); + if (removeReply) { + return plainBody.remove(utils::removeReplyRegex); + } + return QMatrixClient::prettyPrint(plainBody); + } + if (removeReply) { + return e.plainBody().remove(utils::removeReplyRegex); + } + return e.plainBody(); }, [this](const RoomMemberEvent& e) { // FIXME: Rewind to the name that was at the time of this event @@ -478,7 +497,7 @@ void SpectralRoom::postPlainMessage(const QString& text, replyEventId + "\">In reply to " + replyEvt.senderId() + "
" + - utils::removeReply(eventToString(replyEvt, Qt::RichText)) + + eventToString(replyEvt, Qt::RichText) + "" + text.toHtmlEscaped()}}; postJson("m.room.message", json); @@ -513,7 +532,7 @@ void SpectralRoom::postHtmlMessage(const QString& text, replyEventId + "\">In reply to " + replyEvt.senderId() + "
" + - utils::removeReply(eventToString(replyEvt, Qt::RichText)) + + eventToString(replyEvt, Qt::RichText) + "" + html}}; postJson("m.room.message", json); diff --git a/src/spectralroom.h b/src/spectralroom.h index 60c61458d..b7ed4e730 100644 --- a/src/spectralroom.h +++ b/src/spectralroom.h @@ -70,7 +70,7 @@ class SpectralRoom : public Room { QString avatarMediaId() const; QString eventToString(const RoomEvent& evt, - Qt::TextFormat format = Qt::PlainText) const; + Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const; private: QString m_cachedInput; diff --git a/src/utils.cpp b/src/utils.cpp index 5571575eb..6a9dd984b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,15 +1 @@ #include "utils.h" - -QString utils::removeReply(const QString& text) { - QString result(text); - result.remove(utils::removeRichReplyRegex); - result.remove(utils::removeReplyRegex); - return result; -} - -QString utils::cleanHTML(const QString& text) { - QString result(text); - result.replace(codePillRegExp, "\\1"); - result.replace(userPillRegExp, "\\1"); - return result; -} diff --git a/src/utils.h b/src/utils.h index 81a1231bb..f9282d90f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -19,13 +19,12 @@ static const QRegularExpression removeReplyRegex{ static const QRegularExpression removeRichReplyRegex{ ".*?", QRegularExpression::DotMatchesEverythingOption}; static const QRegularExpression codePillRegExp{ - "
(.*?)
", QRegularExpression::DotMatchesEverythingOption}; + "
]*>(.*?)
", QRegularExpression::DotMatchesEverythingOption}; static const QRegularExpression userPillRegExp{ "(.*?)", QRegularExpression::DotMatchesEverythingOption}; - -QString removeReply(const QString& text); -QString cleanHTML(const QString& text); +static const QRegularExpression strikethroughRegExp{ + "(.*?)", QRegularExpression::DotMatchesEverythingOption}; } // namespace utils #endif