Move reply pane to use MessageContentModel

Move reply pane to use MessageContentModel. This means the reply pane component is no longer required.

This commit also limits the size of code and image componets in a reply to keep them from getting too huge.
This commit is contained in:
James Graham
2024-09-15 08:39:22 +00:00
parent ec6a8dd028
commit 1821d9fc04
8 changed files with 80 additions and 116 deletions

View File

@@ -51,7 +51,7 @@ void ChatBarCacheTest::empty()
QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString()); QCOMPARE(chatBarCache->editId(), QString());
QCOMPARE(chatBarCache->relationUser(), room->member(QString())); QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->relationMessage(), QString());
QCOMPARE(chatBarCache->attachmentPath(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QString());
} }
@@ -65,7 +65,7 @@ void ChatBarCacheTest::noRoom()
// ChatBarCache has no parent. // ChatBarCache has no parent.
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."); 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."); QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->relationMessage(), QString());
@@ -81,7 +81,7 @@ void ChatBarCacheTest::badParent()
// ChatBarCache has no parent. // ChatBarCache has no parent.
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."); 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."); QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->relationMessage(), QString());
@@ -99,7 +99,7 @@ void ChatBarCacheTest::reply()
QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org")); QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org"));
QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString()); 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->relationMessage(), QLatin1String("This is an example\ntext message"));
QCOMPARE(chatBarCache->attachmentPath(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QString());
} }
@@ -121,7 +121,7 @@ void ChatBarCacheTest::edit()
QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), true); QCOMPARE(chatBarCache->isEditing(), true);
QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org")); 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->relationMessage(), QLatin1String("This is an example\ntext message"));
QCOMPARE(chatBarCache->attachmentPath(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QString());
} }
@@ -138,7 +138,7 @@ void ChatBarCacheTest::attachment()
QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString()); QCOMPARE(chatBarCache->editId(), QString());
QCOMPARE(chatBarCache->relationUser(), room->member(QString())); QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->relationMessage(), QString());
QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path")); QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path"));
} }

View File

@@ -11,7 +11,6 @@ ecm_add_qml_module(chatbar GENERATE_PLUGIN_SOURCE
CompletionMenu.qml CompletionMenu.qml
EmojiDelegate.qml EmojiDelegate.qml
EmojiGrid.qml EmojiGrid.qml
ReplyPane.qml
PieProgressBar.qml PieProgressBar.qml
EmojiPicker.qml EmojiPicker.qml
EmojiDialog.qml EmojiDialog.qml

View File

@@ -175,6 +175,7 @@ QQC2.Control {
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing Layout.margins: Kirigami.Units.largeSpacing
Layout.preferredHeight: active ? item.implicitHeight : 0
active: visible active: visible
visible: root.currentRoom.mainCache.replyId.length > 0 || root.currentRoom.mainCache.attachmentPath.length > 0 visible: root.currentRoom.mainCache.replyId.length > 0 || root.currentRoom.mainCache.attachmentPath.length > 0
@@ -361,15 +362,32 @@ QQC2.Control {
Component { Component {
id: replyPane id: replyPane
ReplyPane { Item {
userName: _private.chatBarCache.relationUser.displayName implicitWidth: replyComponent.implicitWidth
userColor: _private.chatBarCache.relationUser.color implicitHeight: replyComponent.implicitHeight
userAvatar: _private.chatBarCache.relationUser.avatarUrl ReplyComponent {
text: _private.chatBarCache.relationMessage id: replyComponent
replyEventId: _private.chatBarCache.replyId
replyAuthor: _private.chatBarCache.relationAuthor
replyContentModel: _private.chatBarCache.relationEventContentModel
maxContentWidth: paneLoader.item.width
}
QQC2.Button {
id: cancelButton
onCancel: { anchors.top: parent.top
_private.chatBarCache.replyId = ""; anchors.right: parent.right
_private.chatBarCache.attachmentPath = "";
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
} }
} }
} }

View File

@@ -1,98 +0,0 @@
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.de>
// SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com>
// 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: "<style> a{color:" + Kirigami.Theme.linkColor + ";}.user-pill{}</style>" + 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
}
}

View File

@@ -7,6 +7,7 @@
#include "chatdocumenthandler.h" #include "chatdocumenthandler.h"
#include "eventhandler.h" #include "eventhandler.h"
#include "messagecontentmodel.h"
#include "neochatroom.h" #include "neochatroom.h"
ChatBarCache::ChatBarCache(QObject *parent) ChatBarCache::ChatBarCache(QObject *parent)
@@ -53,6 +54,7 @@ void ChatBarCache::setReplyId(const QString &replyId)
m_relationType = Reply; m_relationType = Reply;
} }
m_attachmentPath = QString(); m_attachmentPath = QString();
delete m_relationContentModel;
Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT relationIdChanged(oldEventId, m_relationId);
Q_EMIT attachmentPathChanged(); Q_EMIT attachmentPathChanged();
} }
@@ -82,11 +84,12 @@ void ChatBarCache::setEditId(const QString &editId)
m_relationType = Edit; m_relationType = Edit;
} }
m_attachmentPath = QString(); m_attachmentPath = QString();
delete m_relationContentModel;
Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT relationIdChanged(oldEventId, m_relationId);
Q_EMIT attachmentPathChanged(); Q_EMIT attachmentPathChanged();
} }
Quotient::RoomMember ChatBarCache::relationUser() const Quotient::RoomMember ChatBarCache::relationAuthor() const
{ {
if (parent() == nullptr) { if (parent() == nullptr) {
qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; 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 {}; 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<NeoChatRoom *>(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 bool ChatBarCache::isThreaded() const
{ {
return !m_threadId.isEmpty(); return !m_threadId.isEmpty();
@@ -156,6 +181,7 @@ void ChatBarCache::setAttachmentPath(const QString &attachmentPath)
m_attachmentPath = attachmentPath; m_attachmentPath = attachmentPath;
m_relationType = None; m_relationType = None;
const auto oldEventId = std::exchange(m_relationId, QString()); const auto oldEventId = std::exchange(m_relationId, QString());
delete m_relationContentModel;
Q_EMIT attachmentPathChanged(); Q_EMIT attachmentPathChanged();
Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT relationIdChanged(oldEventId, m_relationId);
} }
@@ -165,6 +191,7 @@ void ChatBarCache::clearRelations()
const auto oldEventId = std::exchange(m_relationId, QString()); const auto oldEventId = std::exchange(m_relationId, QString());
const auto oldThreadId = std::exchange(m_threadId, QString()); const auto oldThreadId = std::exchange(m_threadId, QString());
m_attachmentPath = QString(); m_attachmentPath = QString();
delete m_relationContentModel;
Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT relationIdChanged(oldEventId, m_relationId);
Q_EMIT threadIdChanged(oldThreadId, m_threadId); Q_EMIT threadIdChanged(oldThreadId, m_threadId);
Q_EMIT attachmentPathChanged(); Q_EMIT attachmentPathChanged();

View File

@@ -8,6 +8,8 @@
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include <QTextCursor> #include <QTextCursor>
#include "models/messagecontentmodel.h"
class ChatDocumentHandler; class ChatDocumentHandler;
namespace Quotient namespace Quotient
@@ -100,7 +102,7 @@ class ChatBarCache : public QObject
* *
* @sa Quotient::RoomMember * @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. * @brief The content of the related message.
@@ -109,6 +111,13 @@ class ChatBarCache : public QObject
*/ */
Q_PROPERTY(QString relationMessage READ relationMessage NOTIFY relationIdChanged) 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. * @brief Whether the chat bar is replying in a thread.
*/ */
@@ -154,9 +163,10 @@ public:
QString editId() const; QString editId() const;
void setEditId(const QString &editId); void setEditId(const QString &editId);
Quotient::RoomMember relationUser() const; Quotient::RoomMember relationAuthor() const;
QString relationMessage() const; QString relationMessage() const;
MessageContentModel *relationEventContentModel();
bool isThreaded() const; bool isThreaded() const;
QString threadId() const; QString threadId() const;
@@ -206,4 +216,6 @@ private:
QString m_attachmentPath = QString(); QString m_attachmentPath = QString();
QList<Mention> m_mentions; QList<Mention> m_mentions;
QString m_savedText; QString m_savedText;
QPointer<MessageContentModel> m_relationContentModel;
}; };

View File

@@ -53,6 +53,8 @@ RowLayout {
*/ */
signal replyClicked(string eventID) signal replyClicked(string eventID)
Layout.fillWidth: true
spacing: Kirigami.Units.largeSpacing spacing: Kirigami.Units.largeSpacing
Rectangle { Rectangle {

View File

@@ -5,6 +5,8 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Qt.labs.qmlmodels import Qt.labs.qmlmodels
import org.kde.kirigami as Kirigami
import org.kde.neochat import org.kde.neochat
/** /**
@@ -60,6 +62,7 @@ DelegateChooser {
MediaSizeHelper { MediaSizeHelper {
id: mediaSizeHelper id: mediaSizeHelper
contentMaxWidth: root.maxContentWidth contentMaxWidth: root.maxContentWidth
contentMaxHeight: Kirigami.Units.gridUnit * 5
mediaWidth: image.mediaInfo.width ?? 0 mediaWidth: image.mediaInfo.width ?? 0
mediaHeight: image.mediaInfo.height ?? 0 mediaHeight: image.mediaInfo.height ?? 0
} }
@@ -81,6 +84,7 @@ DelegateChooser {
DelegateChoice { DelegateChoice {
roleValue: MessageComponentType.Code roleValue: MessageComponentType.Code
delegate: CodeComponent { delegate: CodeComponent {
Layout.maximumHeight: Kirigami.Units.gridUnit * 5
maxContentWidth: root.maxContentWidth maxContentWidth: root.maxContentWidth
MouseArea { MouseArea {