diff --git a/imports/Spectral/Component/Timeline/MessageDelegate.qml b/imports/Spectral/Component/Timeline/MessageDelegate.qml
index 2baf43a2a..c92d1d0d8 100644
--- a/imports/Spectral/Component/Timeline/MessageDelegate.qml
+++ b/imports/Spectral/Component/Timeline/MessageDelegate.qml
@@ -93,40 +93,106 @@ ColumnLayout {
}
}
- contentItem: TextEdit {
- Layout.fillWidth: true
+ contentItem: ColumnLayout {
+ Control {
+ Layout.fillWidth: true
- id: contentLabel
+ visible: replyEventId || ""
- text: "" + display
+ background: MouseArea {
+ onClicked: goToEvent(replyEventId)
+ }
- color: "white"
+ contentItem: RowLayout {
+ spacing: 4
- font.family: CommonFont.font.family
- font.pixelSize: 14
- selectByMouse: true
- readOnly: true
- wrapMode: Label.Wrap
- selectedTextColor: Material.accent
- selectionColor: "white"
- textFormat: Text.RichText
+ Rectangle {
+ Layout.preferredWidth: 2
+ Layout.fillHeight: true
- onLinkActivated: {
- if (link.startsWith("https://matrix.to/")) {
- var result = link.replace(/\?.*/, "").match("https://matrix.to/#/(!.*:.*)/(\\$.*:.*)")
- if (result.length < 3) return
- if (result[1] != currentRoom.id) return
- if (!result[2]) return
- goToEvent(result[2])
- } else {
- Qt.openUrlExternally(link)
+ color: "white"
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+
+ spacing: 0
+
+ Control {
+ padding: 4
+
+ contentItem: RowLayout {
+ spacing: 4
+
+ ImageItem {
+ Layout.preferredWidth: 16
+ Layout.preferredHeight: 16
+
+ source: replyAuthor ? replyAuthor.paintable : null
+ }
+
+ Label {
+ color: "white"
+ text: replyAuthor ? replyAuthor.displayName : ""
+ }
+ }
+
+ background: Rectangle {
+ color: "black"
+ opacity: 0.2
+ radius: height / 2
+ }
+ }
+
+ Label {
+ Layout.fillWidth: true
+
+ text: "" + (replyDisplay ? replyDisplay.replace(/.*<\/mx-reply>/g, "") : "")
+
+ color: "white"
+
+ wrapMode: Label.Wrap
+ textFormat: Label.RichText
+ }
+ }
}
}
- MouseArea {
- anchors.fill: parent
- acceptedButtons: Qt.NoButton
- cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
+ TextEdit {
+ Layout.fillWidth: true
+
+ id: contentLabel
+
+ text: "" + (replyEventId ? display.replace(/.*<\/mx-reply>/g, "") : display)
+
+ color: "white"
+
+ font.family: CommonFont.font.family
+ font.pixelSize: 14
+ selectByMouse: true
+ readOnly: true
+ wrapMode: Label.Wrap
+ selectedTextColor: Material.accent
+ selectionColor: "white"
+ textFormat: Text.RichText
+
+ onLinkActivated: {
+ if (link.startsWith("https://matrix.to/")) {
+ var result = link.replace(/\?.*/, "").match("https://matrix.to/#/(!.*:.*)/(\\$.*:.*)")
+ if (result.length < 3) return
+ if (result[1] != currentRoom.id) return
+ if (!result[2]) return
+ goToEvent(result[2])
+ } else {
+ Qt.openUrlExternally(link)
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+ cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
+ }
}
}
}
diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp
index 6973b68c1..1c1956dd0 100644
--- a/src/messageeventmodel.cpp
+++ b/src/messageeventmodel.cpp
@@ -39,6 +39,9 @@ QHash MessageEventModel::roleNames() const {
roles[LongOperationRole] = "progressInfo";
roles[AnnotationRole] = "annotation";
roles[EventResolvedTypeRole] = "eventResolvedType";
+ roles[ReplyEventIdRole] = "replyEventId";
+ roles[ReplyAuthorRole] = "replyAuthor";
+ roles[ReplyDisplayRole] = "replyDisplay";
roles[UserMarkerRole] = "userMarker";
return roles;
}
@@ -372,6 +375,28 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
return variantList;
}
+ if (role == ReplyEventIdRole || role == ReplyDisplayRole ||
+ role == ReplyAuthorRole) {
+ const QString &replyEventId = evt.contentJson()["m.relates_to"]
+ .toObject()["m.in_reply_to"]
+ .toObject()["event_id"]
+ .toString();
+ if (replyEventId.isEmpty()) return {};
+ const auto replyIt = m_currentRoom->findInTimeline(replyEventId);
+ if (replyIt == m_currentRoom->timelineEdge()) return {};
+ const auto& replyEvt = **replyIt;
+ switch (role) {
+ case ReplyEventIdRole:
+ return replyEventId;
+ case ReplyDisplayRole:
+ return utils::eventToString(replyEvt, m_currentRoom, Qt::RichText);
+ case ReplyAuthorRole:
+ return QVariant::fromValue(
+ m_currentRoom->user(replyEvt.senderId()));
+ }
+ return {};
+ }
+
if (role == AboveEventTypeRole || role == AboveSectionRole ||
role == AboveAuthorRole || role == AboveTimeRole)
for (auto r = row + 1; r < rowCount(); ++r) {
diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h
index b211c8ddc..a828f9936 100644
--- a/src/messageeventmodel.h
+++ b/src/messageeventmodel.h
@@ -30,6 +30,9 @@ class MessageEventModel : public QAbstractListModel {
LongOperationRole,
AnnotationRole,
UserMarkerRole,
+ ReplyEventIdRole,
+ ReplyAuthorRole,
+ ReplyDisplayRole,
// For debugging
EventResolvedTypeRole,
};