diff --git a/autotests/chatbarcachetest.cpp b/autotests/chatbarcachetest.cpp index fbfa00838..839b2dba4 100644 --- a/autotests/chatbarcachetest.cpp +++ b/autotests/chatbarcachetest.cpp @@ -51,7 +51,7 @@ void ChatBarCacheTest::empty() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->member(QString())); + QCOMPARE(chatBarCache->relationAuthor(), room->member(QString())); QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -65,7 +65,7 @@ void ChatBarCacheTest::noRoom() // ChatBarCache has no parent. QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."); - QCOMPARE(chatBarCache->relationUser(), Quotient::RoomMember()); + QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember()); QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."); QCOMPARE(chatBarCache->relationMessage(), QString()); @@ -81,7 +81,7 @@ void ChatBarCacheTest::badParent() // ChatBarCache has no parent. QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."); - QCOMPARE(chatBarCache->relationUser(), Quotient::RoomMember()); + QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember()); QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."); QCOMPARE(chatBarCache->relationMessage(), QString()); @@ -99,7 +99,7 @@ void ChatBarCacheTest::reply() QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org")); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->member(QLatin1String("@example:example.org"))); + QCOMPARE(chatBarCache->relationAuthor(), room->member(QLatin1String("@example:example.org"))); QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message")); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -121,7 +121,7 @@ void ChatBarCacheTest::edit() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), true); QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org")); - QCOMPARE(chatBarCache->relationUser(), room->member(QLatin1String("@example:example.org"))); + QCOMPARE(chatBarCache->relationAuthor(), room->member(QLatin1String("@example:example.org"))); QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message")); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -138,7 +138,7 @@ void ChatBarCacheTest::attachment() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->member(QString())); + QCOMPARE(chatBarCache->relationAuthor(), room->member(QString())); QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path")); } diff --git a/src/chatbar/CMakeLists.txt b/src/chatbar/CMakeLists.txt index d977fbfa1..89a65c95d 100644 --- a/src/chatbar/CMakeLists.txt +++ b/src/chatbar/CMakeLists.txt @@ -11,7 +11,6 @@ ecm_add_qml_module(chatbar GENERATE_PLUGIN_SOURCE CompletionMenu.qml EmojiDelegate.qml EmojiGrid.qml - ReplyPane.qml PieProgressBar.qml EmojiPicker.qml EmojiDialog.qml diff --git a/src/chatbar/ChatBar.qml b/src/chatbar/ChatBar.qml index 2ee4fb258..093cd50e7 100644 --- a/src/chatbar/ChatBar.qml +++ b/src/chatbar/ChatBar.qml @@ -175,6 +175,7 @@ QQC2.Control { Layout.fillWidth: true Layout.margins: Kirigami.Units.largeSpacing + Layout.preferredHeight: active ? item.implicitHeight : 0 active: visible visible: root.currentRoom.mainCache.replyId.length > 0 || root.currentRoom.mainCache.attachmentPath.length > 0 @@ -361,15 +362,32 @@ QQC2.Control { Component { id: replyPane - ReplyPane { - userName: _private.chatBarCache.relationUser.displayName - userColor: _private.chatBarCache.relationUser.color - userAvatar: _private.chatBarCache.relationUser.avatarUrl - text: _private.chatBarCache.relationMessage + Item { + implicitWidth: replyComponent.implicitWidth + implicitHeight: replyComponent.implicitHeight + ReplyComponent { + id: replyComponent + replyEventId: _private.chatBarCache.replyId + replyAuthor: _private.chatBarCache.relationAuthor + replyContentModel: _private.chatBarCache.relationEventContentModel + maxContentWidth: paneLoader.item.width + } + QQC2.Button { + id: cancelButton - onCancel: { - _private.chatBarCache.replyId = ""; - _private.chatBarCache.attachmentPath = ""; + anchors.top: parent.top + anchors.right: parent.right + + display: QQC2.AbstractButton.IconOnly + text: i18nc("@action:button", "Cancel reply") + icon.name: "dialog-close" + onClicked: { + _private.chatBarCache.replyId = ""; + _private.chatBarCache.attachmentPath = ""; + } + QQC2.ToolTip.text: text + QQC2.ToolTip.visible: hovered + QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay } } } diff --git a/src/chatbar/ReplyPane.qml b/src/chatbar/ReplyPane.qml deleted file mode 100644 index 36673b272..000000000 --- a/src/chatbar/ReplyPane.qml +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Carl Schwan -// SPDX-FileCopyrightText: 2020 Noah Davis -// SPDX-License-Identifier: GPL-2.0-or-later - -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls as QQC2 - -import org.kde.kirigami as Kirigami -import org.kde.kirigamiaddons.labs.components as KirigamiComponents - -import org.kde.neochat - -RowLayout { - id: root - - property string userName - property color userColor - property url userAvatar: "" - property var text - - signal cancel - - Rectangle { - id: verticalBorder - - Layout.fillHeight: true - - implicitWidth: Kirigami.Units.smallSpacing - color: userColor - } - ColumnLayout { - RowLayout { - KirigamiComponents.Avatar { - id: replyAvatar - - implicitWidth: Kirigami.Units.iconSizes.small - implicitHeight: Kirigami.Units.iconSizes.small - - source: userAvatar - name: userName - color: userColor - } - QQC2.Label { - Layout.fillWidth: true - Layout.alignment: Qt.AlignLeft - - color: userColor - text: userName - elide: Text.ElideRight - } - } - QQC2.TextArea { - id: textArea - - Layout.fillWidth: true - - leftPadding: 0 - rightPadding: 0 - topPadding: 0 - bottomPadding: 0 - text: "" + replyTextMetrics.elidedText - selectByMouse: true - selectByKeyboard: true - readOnly: true - wrapMode: TextEdit.Wrap - textFormat: TextEdit.RichText - background: Item {} - HoverHandler { - cursorShape: textArea.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor - } - - TextMetrics { - id: replyTextMetrics - - text: root.text - font: textArea.font - elide: Qt.ElideRight - elideWidth: textArea.width * 2 - Kirigami.Units.smallSpacing * 2 - } - } - } - QQC2.ToolButton { - id: cancelButton - - Layout.alignment: Qt.AlignVCenter - - display: QQC2.AbstractButton.IconOnly - text: i18nc("@action:button", "Cancel reply") - icon.name: "dialog-close" - onClicked: { - root.cancel(); - } - QQC2.ToolTip.text: text - QQC2.ToolTip.visible: hovered - QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay - } -} diff --git a/src/chatbarcache.cpp b/src/chatbarcache.cpp index 66f7cdda3..08c33c15a 100644 --- a/src/chatbarcache.cpp +++ b/src/chatbarcache.cpp @@ -7,6 +7,7 @@ #include "chatdocumenthandler.h" #include "eventhandler.h" +#include "messagecontentmodel.h" #include "neochatroom.h" ChatBarCache::ChatBarCache(QObject *parent) @@ -53,6 +54,7 @@ void ChatBarCache::setReplyId(const QString &replyId) m_relationType = Reply; } m_attachmentPath = QString(); + delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT attachmentPathChanged(); } @@ -82,11 +84,12 @@ void ChatBarCache::setEditId(const QString &editId) m_relationType = Edit; } m_attachmentPath = QString(); + delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT attachmentPathChanged(); } -Quotient::RoomMember ChatBarCache::relationUser() const +Quotient::RoomMember ChatBarCache::relationAuthor() const { if (parent() == nullptr) { qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; @@ -124,6 +127,28 @@ QString ChatBarCache::relationMessage() const return {}; } +MessageContentModel *ChatBarCache::relationEventContentModel() +{ + if (parent() == nullptr) { + qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; + return nullptr; + } + if (m_relationId.isEmpty()) { + return nullptr; + } + if (m_relationContentModel != nullptr) { + return m_relationContentModel; + } + + auto room = dynamic_cast(parent()); + if (room == nullptr) { + qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."; + return nullptr; + } + m_relationContentModel = new MessageContentModel(room, m_relationId, true); + return m_relationContentModel; +} + bool ChatBarCache::isThreaded() const { return !m_threadId.isEmpty(); @@ -156,6 +181,7 @@ void ChatBarCache::setAttachmentPath(const QString &attachmentPath) m_attachmentPath = attachmentPath; m_relationType = None; const auto oldEventId = std::exchange(m_relationId, QString()); + delete m_relationContentModel; Q_EMIT attachmentPathChanged(); Q_EMIT relationIdChanged(oldEventId, m_relationId); } @@ -165,6 +191,7 @@ void ChatBarCache::clearRelations() const auto oldEventId = std::exchange(m_relationId, QString()); const auto oldThreadId = std::exchange(m_threadId, QString()); m_attachmentPath = QString(); + delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT threadIdChanged(oldThreadId, m_threadId); Q_EMIT attachmentPathChanged(); diff --git a/src/chatbarcache.h b/src/chatbarcache.h index 7278af5b3..7c32392b5 100644 --- a/src/chatbarcache.h +++ b/src/chatbarcache.h @@ -8,6 +8,8 @@ #include #include +#include "models/messagecontentmodel.h" + class ChatDocumentHandler; namespace Quotient @@ -100,7 +102,7 @@ class ChatBarCache : public QObject * * @sa Quotient::RoomMember */ - Q_PROPERTY(Quotient::RoomMember relationUser READ relationUser NOTIFY relationIdChanged) + Q_PROPERTY(Quotient::RoomMember relationAuthor READ relationAuthor NOTIFY relationIdChanged) /** * @brief The content of the related message. @@ -109,6 +111,13 @@ class ChatBarCache : public QObject */ Q_PROPERTY(QString relationMessage READ relationMessage NOTIFY relationIdChanged) + /** + * @brief The MessageContentModel for the related message. + * + * Will be nullptr if no related message. + */ + Q_PROPERTY(MessageContentModel *relationEventContentModel READ relationEventContentModel NOTIFY relationIdChanged) + /** * @brief Whether the chat bar is replying in a thread. */ @@ -154,9 +163,10 @@ public: QString editId() const; void setEditId(const QString &editId); - Quotient::RoomMember relationUser() const; + Quotient::RoomMember relationAuthor() const; QString relationMessage() const; + MessageContentModel *relationEventContentModel(); bool isThreaded() const; QString threadId() const; @@ -206,4 +216,6 @@ private: QString m_attachmentPath = QString(); QList m_mentions; QString m_savedText; + + QPointer m_relationContentModel; }; diff --git a/src/timeline/ReplyComponent.qml b/src/timeline/ReplyComponent.qml index 73172b064..fa23ff19e 100644 --- a/src/timeline/ReplyComponent.qml +++ b/src/timeline/ReplyComponent.qml @@ -53,6 +53,8 @@ RowLayout { */ signal replyClicked(string eventID) + Layout.fillWidth: true + spacing: Kirigami.Units.largeSpacing Rectangle { diff --git a/src/timeline/ReplyMessageComponentChooser.qml b/src/timeline/ReplyMessageComponentChooser.qml index 0e41e637c..7fca5aa9b 100644 --- a/src/timeline/ReplyMessageComponentChooser.qml +++ b/src/timeline/ReplyMessageComponentChooser.qml @@ -5,6 +5,8 @@ import QtQuick import QtQuick.Layouts import Qt.labs.qmlmodels +import org.kde.kirigami as Kirigami + import org.kde.neochat /** @@ -60,6 +62,7 @@ DelegateChooser { MediaSizeHelper { id: mediaSizeHelper contentMaxWidth: root.maxContentWidth + contentMaxHeight: Kirigami.Units.gridUnit * 5 mediaWidth: image.mediaInfo.width ?? 0 mediaHeight: image.mediaInfo.height ?? 0 } @@ -81,6 +84,7 @@ DelegateChooser { DelegateChoice { roleValue: MessageComponentType.Code delegate: CodeComponent { + Layout.maximumHeight: Kirigami.Units.gridUnit * 5 maxContentWidth: root.maxContentWidth MouseArea {